@memberjunction/react-runtime 2.94.0 → 2.96.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 (50) hide show
  1. package/.turbo/turbo-build.log +9 -9
  2. package/CHANGELOG.md +30 -0
  3. package/dist/compiler/component-compiler.d.ts +1 -0
  4. package/dist/compiler/component-compiler.d.ts.map +1 -1
  5. package/dist/compiler/component-compiler.js +116 -29
  6. package/dist/compiler/component-compiler.js.map +1 -1
  7. package/dist/index.d.ts +2 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +5 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/registry/component-registry-service.d.ts +2 -0
  12. package/dist/registry/component-registry-service.d.ts.map +1 -1
  13. package/dist/registry/component-registry-service.js +25 -6
  14. package/dist/registry/component-registry-service.js.map +1 -1
  15. package/dist/registry/component-registry.d.ts +2 -0
  16. package/dist/registry/component-registry.d.ts.map +1 -1
  17. package/dist/registry/component-registry.js +17 -0
  18. package/dist/registry/component-registry.js.map +1 -1
  19. package/dist/registry/component-resolver.d.ts.map +1 -1
  20. package/dist/registry/component-resolver.js +101 -6
  21. package/dist/registry/component-resolver.js.map +1 -1
  22. package/dist/runtime/component-hierarchy.d.ts.map +1 -1
  23. package/dist/runtime/component-hierarchy.js +73 -17
  24. package/dist/runtime/component-hierarchy.js.map +1 -1
  25. package/dist/runtime.umd.js +1 -1
  26. package/dist/types/index.d.ts +1 -1
  27. package/dist/types/index.d.ts.map +1 -1
  28. package/dist/types/index.js.map +1 -1
  29. package/dist/utilities/core-libraries.d.ts +1 -2
  30. package/dist/utilities/core-libraries.d.ts.map +1 -1
  31. package/dist/utilities/core-libraries.js +55 -45
  32. package/dist/utilities/core-libraries.js.map +1 -1
  33. package/dist/utilities/library-dependency-resolver.d.ts.map +1 -1
  34. package/dist/utilities/library-dependency-resolver.js +42 -9
  35. package/dist/utilities/library-dependency-resolver.js.map +1 -1
  36. package/dist/utilities/library-loader.d.ts +4 -2
  37. package/dist/utilities/library-loader.d.ts.map +1 -1
  38. package/dist/utilities/library-loader.js +27 -6
  39. package/dist/utilities/library-loader.js.map +1 -1
  40. package/package.json +5 -5
  41. package/src/compiler/component-compiler.ts +135 -31
  42. package/src/index.ts +7 -1
  43. package/src/registry/component-registry-service.ts +36 -6
  44. package/src/registry/component-registry.ts +28 -0
  45. package/src/registry/component-resolver.ts +123 -10
  46. package/src/runtime/component-hierarchy.ts +97 -31
  47. package/src/types/index.ts +1 -1
  48. package/src/utilities/core-libraries.ts +60 -46
  49. package/src/utilities/library-dependency-resolver.ts +51 -12
  50. package/src/utilities/library-loader.ts +30 -6
@@ -68,16 +68,37 @@ export class ComponentResolver {
68
68
  namespace: string = 'Global',
69
69
  contextUser?: UserInfo
70
70
  ): Promise<ResolvedComponents> {
71
+ if (this.debug) {
72
+ console.log(`🚀 [ComponentResolver] Starting component resolution for: ${spec.name}`);
73
+ }
74
+ if (this.debug) {
75
+ console.log(`📋 [ComponentResolver] Dependencies to resolve:`, (spec.dependencies || []).map(d => ({
76
+ name: d.name,
77
+ location: d.location,
78
+ namespace: d.namespace
79
+ })));
80
+ }
81
+
71
82
  const resolved: ResolvedComponents = {};
72
83
 
73
84
  // Initialize component engine if we have registry service
74
85
  if (this.registryService) {
86
+ if (this.debug) {
87
+ console.log(`🔄 [ComponentResolver] Initializing component engine...`);
88
+ }
75
89
  await this.componentEngine.Config(false, contextUser);
90
+ if (this.debug) {
91
+ console.log(`✅ [ComponentResolver] Component engine initialized with ${this.componentEngine.Components?.length || 0} components`);
92
+ }
76
93
  }
77
94
 
78
95
  // Resolve the component hierarchy
79
96
  await this.resolveComponentHierarchy(spec, resolved, namespace, new Set(), contextUser);
80
97
 
98
+ if (this.debug) {
99
+ console.log(`📊 [ComponentResolver] Resolved components before unwrapping:`, Object.keys(resolved));
100
+ }
101
+
81
102
  // Unwrap component wrappers before returning
82
103
  // Components from the registry come as objects with component/print/refresh properties
83
104
  // We need to extract just the component function for use in child components
@@ -87,17 +108,35 @@ export class ComponentResolver {
87
108
  if (typeof value.component === 'function') {
88
109
  // This is a wrapped component - extract the actual React component function
89
110
  unwrapped[name] = value.component;
111
+ if (this.debug) {
112
+ console.log(`✅ [ComponentResolver] Unwrapped component: ${name} (was object with .component)`);
113
+ }
90
114
  } else {
91
115
  // ComponentObject has a component property but it's not a function
92
- console.error(`Component ${name} has invalid component property:`, typeof value.component, value);
116
+ console.error(`❌ [ComponentResolver] Component ${name} has invalid component property:`, typeof value.component, value);
93
117
  unwrapped[name] = value; // Pass through the problematic value so we can see the error
94
118
  }
95
- } else {
96
- // This is already a plain component function or something else
119
+ } else if (typeof value === 'function') {
120
+ // Already a function - use as is
97
121
  unwrapped[name] = value;
122
+ if (this.debug) {
123
+ console.log(`✅ [ComponentResolver] Component already a function: ${name}`);
124
+ }
125
+ } else {
126
+ // Something else - could be undefined or an error
127
+ console.warn(`⚠️ [ComponentResolver] Component ${name} is not a function or wrapped component:`, typeof value, value);
128
+ unwrapped[name] = value; // Pass through for debugging
98
129
  }
99
130
  }
100
131
 
132
+ if (this.debug) {
133
+ console.log(`🎯 [ComponentResolver] Final resolved components:`, Object.keys(unwrapped).map(name => ({
134
+ name,
135
+ type: typeof unwrapped[name],
136
+ isUndefined: unwrapped[name] === undefined
137
+ })));
138
+ }
139
+
101
140
  return unwrapped;
102
141
  }
103
142
 
@@ -119,6 +158,14 @@ export class ComponentResolver {
119
158
  // Create a unique identifier for this component
120
159
  const componentId = `${spec.namespace || namespace}/${spec.name}@${spec.version || 'latest'}`;
121
160
 
161
+ // Check if already resolved (not just visited)
162
+ if (resolved[spec.name]) {
163
+ if (this.debug) {
164
+ console.log(`⏭️ [ComponentResolver] Component already resolved: ${spec.name}`);
165
+ }
166
+ return;
167
+ }
168
+
122
169
  // Prevent circular dependencies
123
170
  if (visited.has(componentId)) {
124
171
  if (this.debug) {
@@ -128,17 +175,65 @@ export class ComponentResolver {
128
175
  }
129
176
  visited.add(componentId);
130
177
 
178
+ // *** CRITICAL: Process child components FIRST (depth-first, post-order) ***
179
+ if (this.debug) {
180
+ console.log(`🔄 [ComponentResolver] Resolving dependencies for ${spec.name} BEFORE resolving itself`);
181
+ }
182
+ const children = spec.dependencies || [];
183
+ for (const child of children) {
184
+ if (this.debug) {
185
+ console.log(` ↳ [ComponentResolver] Resolving dependency: ${child.name} for parent ${spec.name}`);
186
+ }
187
+ await this.resolveComponentHierarchy(child, resolved, namespace, visited, contextUser);
188
+ }
189
+ if (children.length > 0 && this.debug) {
190
+ console.log(`✅ [ComponentResolver] All ${children.length} dependencies resolved for ${spec.name}, now resolving itself`);
191
+ }
192
+
193
+ // NOW resolve the current component (it can access its dependencies)
131
194
  // Handle based on location
132
195
  if (spec.location === 'registry' && this.registryService) {
133
196
  // Registry component - need to load from database or external source
197
+ if (this.debug) {
198
+ console.log(`🔍 [ComponentResolver] Looking for registry component: ${spec.name} in namespace: ${spec.namespace || namespace}`);
199
+ }
200
+
134
201
  try {
135
202
  // First, try to find the component in the metadata engine
203
+ const allComponents = this.componentEngine.Components || [];
204
+ if (this.debug) {
205
+ console.log(`📊 [ComponentResolver] Total components in engine: ${allComponents.length}`);
206
+ }
207
+
208
+ // Log all matching names to see duplicates
209
+ const matchingNames = allComponents.filter((c: any) => c.Name === spec.name);
210
+ if (matchingNames.length > 0 && this.debug) {
211
+ console.log(`🔎 [ComponentResolver] Found ${matchingNames.length} components with name "${spec.name}":`,
212
+ matchingNames.map((c: any) => ({
213
+ ID: c.ID,
214
+ Name: c.Name,
215
+ Namespace: c.Namespace,
216
+ Version: c.Version,
217
+ Status: c.Status
218
+ }))
219
+ );
220
+ }
221
+
136
222
  const component = this.componentEngine.Components?.find(
137
223
  (c: any) => c.Name === spec.name &&
138
224
  c.Namespace === (spec.namespace || namespace)
139
225
  );
140
226
 
141
227
  if (component) {
228
+ if (this.debug) {
229
+ console.log(`✅ [ComponentResolver] Found component in DB:`, {
230
+ ID: component.ID,
231
+ Name: component.Name,
232
+ Namespace: component.Namespace,
233
+ Version: component.Version
234
+ });
235
+ }
236
+
142
237
  // Get compiled component from registry service
143
238
  const compiledComponent = await this.registryService.getCompiledComponent(
144
239
  component.ID,
@@ -146,10 +241,15 @@ export class ComponentResolver {
146
241
  contextUser
147
242
  );
148
243
  resolved[spec.name] = compiledComponent;
244
+ if (this.debug) {
245
+ console.log(`📦 [ComponentResolver] Successfully compiled and resolved: ${spec.name}, type: ${typeof compiledComponent}`);
246
+ }
247
+
149
248
  if (this.debug) {
150
249
  console.log(`📦 Resolved registry component: ${spec.name} from ${componentId}`);
151
250
  }
152
251
  } else {
252
+ console.error(`❌❌❌❌❌ [ComponentResolver] Registry component NOT found in database: ${spec.name} with namespace: ${spec.namespace || namespace} ❌❌❌❌`);
153
253
  if (this.debug) {
154
254
  console.warn(`Registry component not found in database: ${spec.name}`);
155
255
  }
@@ -163,34 +263,47 @@ export class ComponentResolver {
163
263
  // Embedded component - get from local registry
164
264
  // Use the component's specified namespace if it has one, otherwise use parent's namespace
165
265
  const componentNamespace = spec.namespace || namespace;
266
+ if (this.debug) {
267
+ console.log(`🔍 [ComponentResolver] Looking for embedded component: ${spec.name} in namespace: ${componentNamespace}`);
268
+ }
269
+
166
270
  const component = this.registry.get(spec.name, componentNamespace);
167
271
  if (component) {
168
272
  resolved[spec.name] = component;
273
+ if (this.debug) {
274
+ console.log(`✅ [ComponentResolver] Found embedded component: ${spec.name}, type: ${typeof component}`);
275
+ }
169
276
  if (this.debug) {
170
277
  console.log(`📄 Resolved embedded component: ${spec.name} from namespace ${componentNamespace}, type:`, typeof component);
171
278
  }
172
279
  } else {
173
280
  // If not found with specified namespace, try the parent namespace as fallback
281
+ if (this.debug) {
282
+ console.log(`⚠️ [ComponentResolver] Not found in namespace ${componentNamespace}, trying fallback namespace: ${namespace}`);
283
+ }
174
284
  const fallbackComponent = this.registry.get(spec.name, namespace);
175
285
  if (fallbackComponent) {
176
286
  resolved[spec.name] = fallbackComponent;
287
+ if (this.debug) {
288
+ console.log(`✅ [ComponentResolver] Found embedded component in fallback namespace: ${spec.name}, type: ${typeof fallbackComponent}`);
289
+ }
177
290
  if (this.debug) {
178
291
  console.log(`📄 Resolved embedded component: ${spec.name} from fallback namespace ${namespace}, type:`, typeof fallbackComponent);
179
292
  }
180
293
  } else {
181
294
  // Component not found - this might cause issues later
182
- console.warn(`⚠️ Could not resolve embedded component: ${spec.name} in namespace ${componentNamespace} or ${namespace}`);
295
+ console.error(`❌ [ComponentResolver] Could not resolve embedded component: ${spec.name} in namespace ${componentNamespace} or ${namespace}`);
296
+ if (this.debug) {
297
+ console.warn(`⚠️ Could not resolve embedded component: ${spec.name} in namespace ${componentNamespace} or ${namespace}`);
298
+ }
183
299
  // Store undefined explicitly so we know it failed to resolve
184
300
  resolved[spec.name] = undefined;
185
301
  }
186
302
  }
187
303
  }
188
-
189
- // Process child components recursively
190
- const children = spec.dependencies || [];
191
- for (const child of children) {
192
- await this.resolveComponentHierarchy(child, resolved, namespace, visited, contextUser);
193
- }
304
+
305
+ // Child components have already been processed at the beginning of this method
306
+ // No need to process them again - we're using depth-first, post-order traversal
194
307
  }
195
308
 
196
309
  /**
@@ -7,7 +7,8 @@
7
7
  import {
8
8
  CompilationResult,
9
9
  CompileOptions,
10
- RuntimeContext
10
+ RuntimeContext,
11
+ CompiledComponent
11
12
  } from '../types';
12
13
  import { ComponentCompiler } from '../compiler';
13
14
  import { ComponentRegistry } from '../registry';
@@ -94,31 +95,97 @@ export class ComponentHierarchyRegistrar {
94
95
  const errors: ComponentRegistrationError[] = [];
95
96
  const warnings: string[] = [];
96
97
 
97
- // Register the root component
98
- const rootResult = await this.registerSingleComponent(
99
- rootSpec,
100
- { styles, namespace, version, allowOverride, allLibraries: options.allLibraries }
101
- );
102
-
103
- if (rootResult.success) {
104
- registeredComponents.push(rootSpec.name);
105
- } else {
106
- errors.push(rootResult.error!);
107
- if (!continueOnError) {
108
- return { success: false, registeredComponents, errors, warnings };
98
+ // PHASE 1: Compile all components first (but defer factory execution)
99
+ const compiledMap = new Map<string, CompiledComponent>();
100
+ const specMap = new Map<string, ComponentSpec>();
101
+
102
+ // Helper to compile a component without calling its factory
103
+ const compileOnly = async (spec: ComponentSpec): Promise<{ success: boolean; error?: ComponentRegistrationError }> => {
104
+ if (!spec.code) return { success: true };
105
+
106
+ try {
107
+ const compileOptions: CompileOptions = {
108
+ componentName: spec.name,
109
+ componentCode: spec.code,
110
+ styles,
111
+ libraries: spec.libraries,
112
+ dependencies: spec.dependencies,
113
+ allLibraries: options.allLibraries
114
+ };
115
+
116
+ const result = await this.compiler.compile(compileOptions);
117
+ if (result.success && result.component) {
118
+ compiledMap.set(spec.name, result.component);
119
+ specMap.set(spec.name, spec);
120
+ return { success: true };
121
+ } else {
122
+ return {
123
+ success: false,
124
+ error: {
125
+ componentName: spec.name,
126
+ error: result.error?.message || 'Unknown compilation error',
127
+ phase: 'compilation'
128
+ }
129
+ };
130
+ }
131
+ } catch (error) {
132
+ return {
133
+ success: false,
134
+ error: {
135
+ componentName: spec.name,
136
+ error: error instanceof Error ? error.message : String(error),
137
+ phase: 'compilation'
138
+ }
139
+ };
140
+ }
141
+ };
142
+
143
+ // Compile all components in hierarchy
144
+ const compileQueue = [rootSpec];
145
+ const visited = new Set<string>();
146
+
147
+ while (compileQueue.length > 0) {
148
+ const spec = compileQueue.shift()!;
149
+ if (visited.has(spec.name)) continue;
150
+ visited.add(spec.name);
151
+
152
+ const result = await compileOnly(spec);
153
+ if (!result.success) {
154
+ errors.push(result.error!);
155
+ if (!continueOnError) {
156
+ return { success: false, registeredComponents, errors, warnings };
157
+ }
158
+ }
159
+
160
+ if (spec.dependencies) {
161
+ compileQueue.push(...spec.dependencies);
109
162
  }
110
163
  }
111
-
112
- // Register child components recursively
113
- const childComponents = rootSpec.dependencies || [];
114
- if (childComponents.length > 0) {
115
- const childResult = await this.registerChildComponents(
116
- childComponents,
117
- { styles, namespace, version, continueOnError, allowOverride, allLibraries: options.allLibraries },
118
- registeredComponents,
119
- errors,
120
- warnings
164
+
165
+ // PHASE 2: Execute all factories with components available
166
+ for (const [name, compiled] of compiledMap) {
167
+ const spec = specMap.get(name)!;
168
+
169
+ // Build components object from all registered components
170
+ const components: Record<string, any> = {};
171
+ for (const [depName, depCompiled] of compiledMap) {
172
+ // Call factory to get ComponentObject, then extract React component
173
+ const depObject = depCompiled.factory(this.runtimeContext, styles);
174
+ components[depName] = depObject.component;
175
+ }
176
+
177
+ // Now call factory with components available
178
+ const componentObject = compiled.factory(this.runtimeContext, styles, components);
179
+
180
+ // Register in registry
181
+ this.registry.register(
182
+ spec.name,
183
+ componentObject,
184
+ spec.namespace || namespace,
185
+ version
121
186
  );
187
+
188
+ registeredComponents.push(spec.name);
122
189
  }
123
190
 
124
191
  return {
@@ -198,15 +265,14 @@ export class ComponentHierarchyRegistrar {
198
265
  }
199
266
 
200
267
  // Call the factory to create the ComponentObject
201
- const componentObject = compilationResult.component!.factory(this.runtimeContext, styles);
202
-
203
- // Debug logging to verify ComponentObject structure
204
- console.log(`📦 Registering ComponentObject for ${spec.name}:`, {
205
- hasComponent: 'component' in componentObject,
206
- componentType: typeof componentObject.component,
207
- hasPrint: 'print' in componentObject,
208
- hasRefresh: 'refresh' in componentObject
268
+ // IMPORTANT: We don't pass components here because child components may not be registered yet
269
+ // Components are resolved later when the component is actually rendered
270
+ console.log(`🏭 Calling factory for ${spec.name} with runtime context:`, {
271
+ hasReact: !!this.runtimeContext.React,
272
+ hasReactDOM: !!this.runtimeContext.ReactDOM,
273
+ libraryKeys: Object.keys(this.runtimeContext.libraries || {})
209
274
  });
275
+ const componentObject = compilationResult.component!.factory(this.runtimeContext, styles);
210
276
 
211
277
  // Register the full ComponentObject (not just the React component)
212
278
  this.registry.register(
@@ -13,7 +13,7 @@ import { ComponentLibraryDependency, ComponentStyles, ComponentObject } from '@m
13
13
  */
14
14
  export interface CompiledComponent {
15
15
  /** Factory function that creates a ComponentObject when called with context */
16
- factory: (context: RuntimeContext, styles?: ComponentStyles) => ComponentObject;
16
+ factory: (context: RuntimeContext, styles?: ComponentStyles, components?: Record<string, any>) => ComponentObject;
17
17
  /** Unique identifier for the component */
18
18
  id: string;
19
19
  /** Original component name */
@@ -1,61 +1,75 @@
1
1
  import { ExternalLibraryConfig } from '../types/library-config';
2
2
 
3
3
  /**
4
- * Core runtime libraries required for the React runtime to function.
5
- * These are not plugin libraries and are always loaded.
4
+ * Get the React CDN URL based on debug mode
6
5
  */
7
- export const CORE_RUNTIME_LIBRARIES: ExternalLibraryConfig[] = [
8
- {
9
- id: 'react',
10
- name: 'react',
11
- displayName: 'React',
12
- category: 'runtime',
13
- globalVariable: 'React',
14
- version: '18.2.0',
15
- cdnUrl: 'https://unpkg.com/react@18.2.0/umd/react.production.min.js',
16
- description: 'React core library',
17
- isEnabled: true,
18
- isCore: true,
19
- isRuntimeOnly: true
20
- },
21
- {
22
- id: 'react-dom',
23
- name: 'react-dom',
24
- displayName: 'ReactDOM',
25
- category: 'runtime',
26
- globalVariable: 'ReactDOM',
27
- version: '18.2.0',
28
- cdnUrl: 'https://unpkg.com/react-dom@18.2.0/umd/react-dom.production.min.js',
29
- description: 'React DOM library',
30
- isEnabled: true,
31
- isCore: true,
32
- isRuntimeOnly: true
33
- },
34
- {
35
- id: 'babel-standalone',
36
- name: '@babel/standalone',
37
- displayName: 'Babel Standalone',
38
- category: 'runtime',
39
- globalVariable: 'Babel',
40
- version: '7.24.4',
41
- cdnUrl: 'https://unpkg.com/@babel/standalone@7.24.4/babel.min.js',
42
- description: 'Babel compiler for JSX transformation',
43
- isEnabled: true,
44
- isCore: true,
45
- isRuntimeOnly: true
46
- }
47
- ];
6
+ function getReactUrl(debug: boolean = false): string {
7
+ return debug
8
+ ? 'https://unpkg.com/react@18.2.0/umd/react.development.js'
9
+ : 'https://unpkg.com/react@18.2.0/umd/react.production.min.js';
10
+ }
11
+
12
+ /**
13
+ * Get the ReactDOM CDN URL based on debug mode
14
+ */
15
+ function getReactDOMUrl(debug: boolean = false): string {
16
+ return debug
17
+ ? 'https://unpkg.com/react-dom@18.2.0/umd/react-dom.development.js'
18
+ : 'https://unpkg.com/react-dom@18.2.0/umd/react-dom.production.min.js';
19
+ }
48
20
 
49
21
  /**
50
22
  * Get the core runtime libraries configuration
23
+ * @param debug Whether to use development builds for better error messages
51
24
  */
52
- export function getCoreRuntimeLibraries(): ExternalLibraryConfig[] {
53
- return CORE_RUNTIME_LIBRARIES;
25
+ export function getCoreRuntimeLibraries(debug: boolean = false): ExternalLibraryConfig[] {
26
+ return [
27
+ {
28
+ id: 'react',
29
+ name: 'react',
30
+ displayName: 'React',
31
+ category: 'runtime',
32
+ globalVariable: 'React',
33
+ version: '18.2.0',
34
+ cdnUrl: getReactUrl(debug),
35
+ description: 'React core library',
36
+ isEnabled: true,
37
+ isCore: true,
38
+ isRuntimeOnly: true
39
+ },
40
+ {
41
+ id: 'react-dom',
42
+ name: 'react-dom',
43
+ displayName: 'ReactDOM',
44
+ category: 'runtime',
45
+ globalVariable: 'ReactDOM',
46
+ version: '18.2.0',
47
+ cdnUrl: getReactDOMUrl(debug),
48
+ description: 'React DOM library',
49
+ isEnabled: true,
50
+ isCore: true,
51
+ isRuntimeOnly: true
52
+ },
53
+ {
54
+ id: 'babel-standalone',
55
+ name: '@babel/standalone',
56
+ displayName: 'Babel Standalone',
57
+ category: 'runtime',
58
+ globalVariable: 'Babel',
59
+ version: '7.24.4',
60
+ cdnUrl: 'https://unpkg.com/@babel/standalone@7.24.4/babel.min.js',
61
+ description: 'Babel compiler for JSX transformation',
62
+ isEnabled: true,
63
+ isCore: true,
64
+ isRuntimeOnly: true
65
+ }
66
+ ];
54
67
  }
55
68
 
56
69
  /**
57
70
  * Check if a library ID is a core runtime library
58
71
  */
59
72
  export function isCoreRuntimeLibrary(libraryId: string): boolean {
60
- return CORE_RUNTIME_LIBRARIES.some(lib => lib.id === libraryId);
73
+ const coreLibraries = getCoreRuntimeLibraries();
74
+ return coreLibraries.some((lib: ExternalLibraryConfig) => lib.id === libraryId);
61
75
  }
@@ -420,22 +420,43 @@ export class LibraryDependencyResolver {
420
420
  const errors: string[] = [];
421
421
  const warnings: string[] = [];
422
422
 
423
+ // Filter out null, undefined, and non-string values from requestedLibs
424
+ const validRequestedLibs = requestedLibs.filter(lib => {
425
+ if (!lib || typeof lib !== 'string') {
426
+ const warning = `Invalid library name: ${lib} (type: ${typeof lib})`;
427
+ warnings.push(warning);
428
+ if (this.debug || options?.debug) {
429
+ console.warn(`⚠️ ${warning}`);
430
+ }
431
+ return false;
432
+ }
433
+ return true;
434
+ });
435
+
423
436
  if (this.debug || options?.debug) {
424
- console.log('🔍 Getting load order for:', requestedLibs);
437
+ console.log('🔍 Getting load order for requested libraries:');
438
+ console.log(' 📝 Requested (raw):', requestedLibs);
439
+ console.log(' 📝 Requested (valid):', validRequestedLibs);
440
+ console.log(' 📚 Total available libraries:', allLibs.length);
425
441
  }
426
442
 
427
- // Build a map for quick lookup
443
+ // Build a map for quick lookup (case-insensitive)
428
444
  const libMap = new Map<string, ComponentLibraryEntity[]>();
429
445
  for (const lib of allLibs) {
430
- if (!libMap.has(lib.Name)) {
431
- libMap.set(lib.Name, []);
446
+ if (!lib?.Name) {
447
+ warnings.push(`Library with missing name found in available libraries`);
448
+ continue;
432
449
  }
433
- libMap.get(lib.Name)!.push(lib);
450
+ const key = lib.Name.toLowerCase();
451
+ if (!libMap.has(key)) {
452
+ libMap.set(key, []);
453
+ }
454
+ libMap.get(key)!.push(lib);
434
455
  }
435
456
 
436
457
  // Collect all libraries needed (requested + their dependencies)
437
458
  const needed = new Set<string>();
438
- const toProcess = [...requestedLibs];
459
+ const toProcess = [...validRequestedLibs];
439
460
  const processed = new Set<string>();
440
461
  const versionRequirements = new Map<string, VersionRequirement[]>();
441
462
  let depth = 0;
@@ -443,14 +464,28 @@ export class LibraryDependencyResolver {
443
464
 
444
465
  while (toProcess.length > 0 && depth < maxDepth) {
445
466
  const current = toProcess.shift()!;
467
+
468
+ // Extra safety check for null/undefined
469
+ if (!current || typeof current !== 'string') {
470
+ const warning = `Unexpected invalid library name during processing: ${current}`;
471
+ warnings.push(warning);
472
+ if (this.debug || options?.debug) {
473
+ console.warn(`⚠️ ${warning}`);
474
+ }
475
+ continue;
476
+ }
477
+
446
478
  if (processed.has(current)) continue;
447
479
 
448
480
  processed.add(current);
449
481
  needed.add(current);
450
482
 
451
- // Find the library
452
- const libVersions = libMap.get(current);
483
+ // Find the library (case-insensitive lookup)
484
+ const libVersions = libMap.get(current.toLowerCase());
453
485
  if (!libVersions || libVersions.length === 0) {
486
+ if (this.debug || options?.debug) {
487
+ console.log(` ❌ Library '${current}' not found in available libraries`);
488
+ }
454
489
  errors.push(`Library '${current}' not found`);
455
490
  continue;
456
491
  }
@@ -458,6 +493,10 @@ export class LibraryDependencyResolver {
458
493
  // For now, use the first version found (should be resolved properly)
459
494
  const lib = libVersions[0];
460
495
  const deps = this.parseDependencies(lib.Dependencies);
496
+
497
+ if ((this.debug || options?.debug) && deps.size > 0) {
498
+ console.log(` 📌 ${current} requires:`, Array.from(deps.entries()));
499
+ }
461
500
 
462
501
  // Process dependencies
463
502
  for (const [depName, depVersion] of deps) {
@@ -489,7 +528,7 @@ export class LibraryDependencyResolver {
489
528
  const resolvedLibraries: ComponentLibraryEntity[] = [];
490
529
  for (const libName of needed) {
491
530
  const requirements = versionRequirements.get(libName) || [];
492
- const versions = libMap.get(libName) || [];
531
+ const versions = libMap.get(libName.toLowerCase()) || [];
493
532
 
494
533
  if (versions.length === 0) {
495
534
  errors.push(`Library '${libName}' not found`);
@@ -573,10 +612,10 @@ export class LibraryDependencyResolver {
573
612
  const processed = new Set<string>();
574
613
  let depth = 0;
575
614
 
576
- // Build lookup map
615
+ // Build lookup map (case-insensitive)
577
616
  const libMap = new Map<string, ComponentLibraryEntity>();
578
617
  for (const lib of allLibs) {
579
- libMap.set(lib.Name, lib);
618
+ libMap.set(lib.Name.toLowerCase(), lib);
580
619
  }
581
620
 
582
621
  while (toProcess.length > 0 && depth < maxDepth) {
@@ -584,7 +623,7 @@ export class LibraryDependencyResolver {
584
623
  if (processed.has(current)) continue;
585
624
 
586
625
  processed.add(current);
587
- const lib = libMap.get(current);
626
+ const lib = libMap.get(current.toLowerCase());
588
627
  if (!lib) continue;
589
628
 
590
629
  const deps = this.parseDependencies(lib.Dependencies);