@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.
- package/.turbo/turbo-build.log +9 -9
- package/CHANGELOG.md +30 -0
- package/dist/compiler/component-compiler.d.ts +1 -0
- package/dist/compiler/component-compiler.d.ts.map +1 -1
- package/dist/compiler/component-compiler.js +116 -29
- package/dist/compiler/component-compiler.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/registry/component-registry-service.d.ts +2 -0
- package/dist/registry/component-registry-service.d.ts.map +1 -1
- package/dist/registry/component-registry-service.js +25 -6
- package/dist/registry/component-registry-service.js.map +1 -1
- package/dist/registry/component-registry.d.ts +2 -0
- package/dist/registry/component-registry.d.ts.map +1 -1
- package/dist/registry/component-registry.js +17 -0
- package/dist/registry/component-registry.js.map +1 -1
- package/dist/registry/component-resolver.d.ts.map +1 -1
- package/dist/registry/component-resolver.js +101 -6
- package/dist/registry/component-resolver.js.map +1 -1
- package/dist/runtime/component-hierarchy.d.ts.map +1 -1
- package/dist/runtime/component-hierarchy.js +73 -17
- package/dist/runtime/component-hierarchy.js.map +1 -1
- package/dist/runtime.umd.js +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utilities/core-libraries.d.ts +1 -2
- package/dist/utilities/core-libraries.d.ts.map +1 -1
- package/dist/utilities/core-libraries.js +55 -45
- package/dist/utilities/core-libraries.js.map +1 -1
- package/dist/utilities/library-dependency-resolver.d.ts.map +1 -1
- package/dist/utilities/library-dependency-resolver.js +42 -9
- package/dist/utilities/library-dependency-resolver.js.map +1 -1
- package/dist/utilities/library-loader.d.ts +4 -2
- package/dist/utilities/library-loader.d.ts.map +1 -1
- package/dist/utilities/library-loader.js +27 -6
- package/dist/utilities/library-loader.js.map +1 -1
- package/package.json +5 -5
- package/src/compiler/component-compiler.ts +135 -31
- package/src/index.ts +7 -1
- package/src/registry/component-registry-service.ts +36 -6
- package/src/registry/component-registry.ts +28 -0
- package/src/registry/component-resolver.ts +123 -10
- package/src/runtime/component-hierarchy.ts +97 -31
- package/src/types/index.ts +1 -1
- package/src/utilities/core-libraries.ts +60 -46
- package/src/utilities/library-dependency-resolver.ts +51 -12
- 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(
|
|
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
|
-
//
|
|
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.
|
|
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
|
-
//
|
|
190
|
-
|
|
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
|
-
//
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
//
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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(
|
package/src/types/index.ts
CHANGED
|
@@ -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
|
-
*
|
|
5
|
-
* These are not plugin libraries and are always loaded.
|
|
4
|
+
* Get the React CDN URL based on debug mode
|
|
6
5
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
|
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
|
-
|
|
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:'
|
|
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 (!
|
|
431
|
-
|
|
446
|
+
if (!lib?.Name) {
|
|
447
|
+
warnings.push(`Library with missing name found in available libraries`);
|
|
448
|
+
continue;
|
|
432
449
|
}
|
|
433
|
-
|
|
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 = [...
|
|
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);
|