@memberjunction/react-runtime 2.90.0 → 2.92.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 +29 -1
- package/CHANGELOG.md +31 -0
- package/dist/compiler/babel-config.js +1 -0
- package/dist/compiler/babel-config.js.map +1 -0
- package/dist/compiler/component-compiler.d.ts.map +1 -1
- package/dist/compiler/component-compiler.js +64 -14
- package/dist/compiler/component-compiler.js.map +1 -0
- package/dist/compiler/index.js +1 -0
- package/dist/compiler/index.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -0
- package/dist/registry/component-registry.d.ts +1 -0
- package/dist/registry/component-registry.d.ts.map +1 -1
- package/dist/registry/component-registry.js +10 -0
- package/dist/registry/component-registry.js.map +1 -0
- package/dist/registry/component-resolver.js +1 -0
- package/dist/registry/component-resolver.js.map +1 -0
- package/dist/registry/index.js +1 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/runtime/component-hierarchy.d.ts +7 -4
- package/dist/runtime/component-hierarchy.d.ts.map +1 -1
- package/dist/runtime/component-hierarchy.js +20 -6
- package/dist/runtime/component-hierarchy.js.map +1 -0
- package/dist/runtime/error-boundary.js +1 -0
- package/dist/runtime/error-boundary.js.map +1 -0
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/prop-builder.d.ts +2 -1
- package/dist/runtime/prop-builder.d.ts.map +1 -1
- package/dist/runtime/prop-builder.js +1 -0
- package/dist/runtime/prop-builder.js.map +1 -0
- package/dist/runtime/react-root-manager.js +1 -0
- package/dist/runtime/react-root-manager.js.map +1 -0
- package/dist/runtime.umd.js +2 -0
- package/dist/runtime.umd.js.LICENSE.txt +10 -0
- package/dist/types/index.d.ts +8 -6
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/library-config.js +1 -0
- package/dist/types/library-config.js.map +1 -0
- package/dist/utilities/cache-manager.js +1 -0
- package/dist/utilities/cache-manager.js.map +1 -0
- package/dist/utilities/component-error-analyzer.js +1 -0
- package/dist/utilities/component-error-analyzer.js.map +1 -0
- package/dist/utilities/component-styles.js +1 -0
- package/dist/utilities/component-styles.js.map +1 -0
- package/dist/utilities/core-libraries.js +1 -0
- package/dist/utilities/core-libraries.js.map +1 -0
- package/dist/utilities/index.d.ts +0 -1
- package/dist/utilities/index.d.ts.map +1 -1
- package/dist/utilities/index.js +1 -1
- package/dist/utilities/index.js.map +1 -0
- package/dist/utilities/library-loader.d.ts.map +1 -1
- package/dist/utilities/library-loader.js +15 -0
- package/dist/utilities/library-loader.js.map +1 -0
- package/dist/utilities/library-registry.d.ts +3 -1
- package/dist/utilities/library-registry.d.ts.map +1 -1
- package/dist/utilities/library-registry.js +43 -518
- package/dist/utilities/library-registry.js.map +1 -0
- package/dist/utilities/resource-manager.js +1 -0
- package/dist/utilities/resource-manager.js.map +1 -0
- package/dist/utilities/standard-libraries.js +1 -0
- package/dist/utilities/standard-libraries.js.map +1 -0
- package/package.json +16 -6
- package/src/compiler/component-compiler.ts +84 -16
- package/src/index.ts +5 -4
- package/src/registry/component-registry.ts +18 -0
- package/src/runtime/component-hierarchy.ts +29 -8
- package/src/runtime/prop-builder.ts +3 -2
- package/src/types/index.ts +14 -12
- package/src/utilities/index.ts +0 -1
- package/src/utilities/library-loader.ts +18 -0
- package/src/utilities/library-registry.ts +57 -552
- package/tsconfig.json +1 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/webpack.umd.config.js +76 -0
- package/dist/utilities/runtime-utilities.d.ts +0 -10
- package/dist/utilities/runtime-utilities.d.ts.map +0 -1
- package/dist/utilities/runtime-utilities.js +0 -92
- package/src/utilities/runtime-utilities.ts +0 -122
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/react-runtime",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.92.0",
|
|
4
4
|
"description": "Platform-agnostic React component runtime for MemberJunction. Provides core compilation, registry, and execution capabilities for React components in any JavaScript environment.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"browser": "dist/runtime.umd.js",
|
|
7
8
|
"scripts": {
|
|
8
|
-
"build": "
|
|
9
|
+
"build": "npm run build:node && npm run build:umd",
|
|
10
|
+
"build:node": "tsc",
|
|
11
|
+
"build:umd": "webpack --config webpack.umd.config.js",
|
|
9
12
|
"build:clean": "rimraf ./dist && npm run build",
|
|
10
13
|
"watch": "tsc -w",
|
|
11
14
|
"patchVersion": "npm version patch",
|
|
@@ -25,9 +28,10 @@
|
|
|
25
28
|
},
|
|
26
29
|
"homepage": "https://github.com/MemberJunction/MJ#readme",
|
|
27
30
|
"dependencies": {
|
|
28
|
-
"@memberjunction/core": "2.
|
|
29
|
-
"@memberjunction/global": "2.
|
|
30
|
-
"@memberjunction/interactive-component-types": "2.
|
|
31
|
+
"@memberjunction/core": "2.92.0",
|
|
32
|
+
"@memberjunction/global": "2.92.0",
|
|
33
|
+
"@memberjunction/interactive-component-types": "2.92.0",
|
|
34
|
+
"@memberjunction/core-entities": "2.92.0",
|
|
31
35
|
"@babel/standalone": "^7.23.5",
|
|
32
36
|
"rxjs": "^7.8.1"
|
|
33
37
|
},
|
|
@@ -35,6 +39,12 @@
|
|
|
35
39
|
"@types/node": "20.10.0",
|
|
36
40
|
"jest": "^27.5.1",
|
|
37
41
|
"rimraf": "^3.0.2",
|
|
38
|
-
"typescript": "~5.3.3"
|
|
42
|
+
"typescript": "~5.3.3",
|
|
43
|
+
"webpack": "^5.89.0",
|
|
44
|
+
"webpack-cli": "^5.1.4",
|
|
45
|
+
"babel-loader": "^9.1.3",
|
|
46
|
+
"@babel/core": "^7.23.5",
|
|
47
|
+
"@babel/preset-env": "^7.23.5",
|
|
48
|
+
"path-browserify": "^1.0.1"
|
|
39
49
|
}
|
|
40
50
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* @module @memberjunction/react-runtime/compiler
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { UserInfo } from '@memberjunction/core';
|
|
7
8
|
import {
|
|
8
9
|
CompileOptions,
|
|
9
10
|
CompiledComponent,
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
RuntimeContext
|
|
14
15
|
} from '../types';
|
|
15
16
|
import { LibraryRegistry } from '../utilities/library-registry';
|
|
17
|
+
import { ComponentLibraryEntity } from '@memberjunction/core-entities';
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
20
|
* Default compiler configuration
|
|
@@ -80,7 +82,7 @@ export class ComponentCompiler {
|
|
|
80
82
|
this.validateCompileOptions(options);
|
|
81
83
|
|
|
82
84
|
// Load required libraries if specified
|
|
83
|
-
const loadedLibraries = await this.loadRequiredLibraries(options.libraries);
|
|
85
|
+
const loadedLibraries = await this.loadRequiredLibraries(options.libraries!, options.allLibraries);
|
|
84
86
|
|
|
85
87
|
// Transpile the component code
|
|
86
88
|
const transpiledCode = this.transpileComponent(
|
|
@@ -142,7 +144,7 @@ export class ComponentCompiler {
|
|
|
142
144
|
throw new Error('Babel instance not set. Call setBabelInstance() first.');
|
|
143
145
|
}
|
|
144
146
|
|
|
145
|
-
const wrappedCode = this.wrapComponentCode(code, componentName, options.libraries);
|
|
147
|
+
const wrappedCode = this.wrapComponentCode(code, componentName, options.libraries, options.dependencies);
|
|
146
148
|
|
|
147
149
|
try {
|
|
148
150
|
const result = this.babelInstance.transform(wrappedCode, {
|
|
@@ -164,9 +166,10 @@ export class ComponentCompiler {
|
|
|
164
166
|
* @param componentCode - Raw component code
|
|
165
167
|
* @param componentName - Name of the component
|
|
166
168
|
* @param libraries - Optional library dependencies
|
|
169
|
+
* @param dependencies - Optional child component dependencies
|
|
167
170
|
* @returns Wrapped component code
|
|
168
171
|
*/
|
|
169
|
-
private wrapComponentCode(componentCode: string, componentName: string, libraries?: any[]): string {
|
|
172
|
+
private wrapComponentCode(componentCode: string, componentName: string, libraries?: any[], dependencies?: Array<{ name: string }>): string {
|
|
170
173
|
// Generate library declarations if libraries are provided
|
|
171
174
|
const libraryDeclarations = libraries && libraries.length > 0
|
|
172
175
|
? libraries
|
|
@@ -174,14 +177,21 @@ export class ComponentCompiler {
|
|
|
174
177
|
.map(lib => `const ${lib.globalVariable} = libraries['${lib.globalVariable}'];`)
|
|
175
178
|
.join('\n ')
|
|
176
179
|
: '';
|
|
180
|
+
|
|
181
|
+
// Generate component declarations if dependencies are provided
|
|
182
|
+
const componentDeclarations = dependencies && dependencies.length > 0
|
|
183
|
+
? dependencies
|
|
184
|
+
.map(dep => `const ${dep.name} = components['${dep.name}'];`)
|
|
185
|
+
.join('\n ')
|
|
186
|
+
: '';
|
|
177
187
|
|
|
178
188
|
return `
|
|
179
189
|
function createComponent(
|
|
180
190
|
React, ReactDOM,
|
|
181
191
|
useState, useEffect, useCallback, useMemo, useRef, useContext, useReducer, useLayoutEffect,
|
|
182
|
-
libraries, styles, console
|
|
192
|
+
libraries, styles, console, components
|
|
183
193
|
) {
|
|
184
|
-
${libraryDeclarations ? libraryDeclarations + '\n ' : ''}${componentCode}
|
|
194
|
+
${libraryDeclarations ? libraryDeclarations + '\n ' : ''}${componentDeclarations ? componentDeclarations + '\n ' : ''}${componentCode}
|
|
185
195
|
|
|
186
196
|
// Ensure the component exists
|
|
187
197
|
if (typeof ${componentName} === 'undefined') {
|
|
@@ -207,12 +217,19 @@ export class ComponentCompiler {
|
|
|
207
217
|
/**
|
|
208
218
|
* Load required libraries from the registry
|
|
209
219
|
* @param libraries - Array of library dependencies
|
|
220
|
+
* @param contextUser - Context user for accessing library registry
|
|
210
221
|
* @returns Map of loaded libraries
|
|
211
222
|
*/
|
|
212
|
-
private async loadRequiredLibraries(libraries
|
|
223
|
+
private async loadRequiredLibraries(libraries: any[], componentLibraries: ComponentLibraryEntity[]): Promise<Map<string, any>> {
|
|
213
224
|
const loadedLibraries = new Map<string, any>();
|
|
214
225
|
|
|
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
|
+
});
|
|
230
|
+
|
|
215
231
|
if (!libraries || libraries.length === 0) {
|
|
232
|
+
console.log('📚 No libraries to load, returning empty map');
|
|
216
233
|
return loadedLibraries;
|
|
217
234
|
}
|
|
218
235
|
|
|
@@ -222,28 +239,49 @@ export class ComponentCompiler {
|
|
|
222
239
|
return loadedLibraries;
|
|
223
240
|
}
|
|
224
241
|
|
|
242
|
+
// Initialize LibraryRegistry with componentLibraries if provided
|
|
243
|
+
if (componentLibraries) {
|
|
244
|
+
await LibraryRegistry.Config(false, componentLibraries);
|
|
245
|
+
} else {
|
|
246
|
+
console.warn('⚠️ No componentLibraries provided for LibraryRegistry initialization');
|
|
247
|
+
}
|
|
248
|
+
|
|
225
249
|
const loadPromises = libraries.map(async (lib) => {
|
|
250
|
+
console.log(`📦 Processing library: ${lib.name}`);
|
|
251
|
+
|
|
226
252
|
// Check if library is approved
|
|
227
|
-
|
|
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`);
|
|
228
258
|
throw new Error(`Library '${lib.name}' is not approved. Only approved libraries can be used.`);
|
|
229
259
|
}
|
|
230
260
|
|
|
231
261
|
// Get library definition for complete info
|
|
232
262
|
const libraryDef = LibraryRegistry.getLibrary(lib.name);
|
|
263
|
+
console.log(` ✓ Library definition found for ${lib.name}: ${!!libraryDef}`);
|
|
264
|
+
|
|
233
265
|
if (!libraryDef) {
|
|
266
|
+
console.error(` ❌ Library '${lib.name}' not found in registry`);
|
|
234
267
|
throw new Error(`Library '${lib.name}' not found in registry`);
|
|
235
268
|
}
|
|
236
269
|
|
|
237
270
|
// Get CDN URL for the library
|
|
238
271
|
const resolvedVersion = LibraryRegistry.resolveVersion(lib.name, lib.version);
|
|
272
|
+
console.log(` ✓ Resolved version for ${lib.name}: ${resolvedVersion}`);
|
|
273
|
+
|
|
239
274
|
const cdnUrl = LibraryRegistry.getCdnUrl(lib.name, resolvedVersion);
|
|
275
|
+
console.log(` ✓ CDN URL for ${lib.name}: ${cdnUrl}`);
|
|
240
276
|
|
|
241
277
|
if (!cdnUrl) {
|
|
278
|
+
console.error(` ❌ No CDN URL found for library '${lib.name}' version '${lib.version || 'default'}'`);
|
|
242
279
|
throw new Error(`No CDN URL found for library '${lib.name}' version '${lib.version || 'default'}'`);
|
|
243
280
|
}
|
|
244
281
|
|
|
245
282
|
// Check if already loaded
|
|
246
283
|
if ((window as any)[lib.globalVariable]) {
|
|
284
|
+
console.log(` ℹ️ Library ${lib.name} already loaded globally as ${lib.globalVariable}`);
|
|
247
285
|
loadedLibraries.set(lib.globalVariable, (window as any)[lib.globalVariable]);
|
|
248
286
|
return;
|
|
249
287
|
}
|
|
@@ -255,20 +293,29 @@ export class ComponentCompiler {
|
|
|
255
293
|
}
|
|
256
294
|
|
|
257
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}...`);
|
|
258
297
|
await this.loadScript(cdnUrl!, lib.globalVariable);
|
|
259
298
|
|
|
260
299
|
// Capture the library value from global scope
|
|
261
300
|
// Note: Libraries loaded from CDN typically attach to window automatically
|
|
262
301
|
// We capture them here to pass through the component's closure
|
|
263
302
|
const libraryValue = (window as any)[lib.globalVariable];
|
|
303
|
+
console.log(` ✓ Library ${lib.name} loaded successfully, global variable ${lib.globalVariable} is:`, typeof libraryValue);
|
|
304
|
+
|
|
264
305
|
if (libraryValue) {
|
|
265
306
|
loadedLibraries.set(lib.globalVariable, libraryValue);
|
|
307
|
+
console.log(` ✅ Added ${lib.name} to loaded libraries map`);
|
|
266
308
|
} else {
|
|
309
|
+
console.error(` ❌ Library '${lib.name}' failed to expose global variable '${lib.globalVariable}'`);
|
|
267
310
|
throw new Error(`Library '${lib.name}' failed to load or did not expose '${lib.globalVariable}'`);
|
|
268
311
|
}
|
|
269
312
|
});
|
|
270
313
|
|
|
271
314
|
await Promise.all(loadPromises);
|
|
315
|
+
|
|
316
|
+
console.log(`✅ All libraries loaded successfully. Total: ${loadedLibraries.size}`);
|
|
317
|
+
console.log('📚 Loaded libraries map:', Array.from(loadedLibraries.keys()));
|
|
318
|
+
|
|
272
319
|
return loadedLibraries;
|
|
273
320
|
}
|
|
274
321
|
|
|
@@ -313,11 +360,16 @@ export class ComponentCompiler {
|
|
|
313
360
|
// Check if script already exists
|
|
314
361
|
const existingScript = document.querySelector(`script[src="${url}"]`);
|
|
315
362
|
if (existingScript) {
|
|
316
|
-
// Wait for it to finish loading
|
|
363
|
+
// Wait for it to finish loading with exponential backoff
|
|
364
|
+
let attempts = 0;
|
|
365
|
+
const maxAttempts = 50; // 5 seconds total with 100ms intervals
|
|
317
366
|
const checkLoaded = () => {
|
|
318
367
|
if ((window as any)[globalName]) {
|
|
319
368
|
resolve();
|
|
369
|
+
} else if (attempts >= maxAttempts) {
|
|
370
|
+
reject(new Error(`${globalName} not found after ${maxAttempts * 100}ms waiting for existing script`));
|
|
320
371
|
} else {
|
|
372
|
+
attempts++;
|
|
321
373
|
setTimeout(checkLoaded, 100);
|
|
322
374
|
}
|
|
323
375
|
};
|
|
@@ -331,14 +383,28 @@ export class ComponentCompiler {
|
|
|
331
383
|
script.async = true;
|
|
332
384
|
|
|
333
385
|
script.onload = () => {
|
|
334
|
-
//
|
|
335
|
-
|
|
386
|
+
// More robust checking with multiple attempts
|
|
387
|
+
let attempts = 0;
|
|
388
|
+
const maxAttempts = 20; // 2 seconds total
|
|
389
|
+
const checkInterval = 100; // Check every 100ms
|
|
390
|
+
|
|
391
|
+
const checkGlobal = () => {
|
|
336
392
|
if ((window as any)[globalName]) {
|
|
393
|
+
console.log(` ✓ Global variable ${globalName} found after ${attempts * checkInterval}ms`);
|
|
337
394
|
resolve();
|
|
395
|
+
} else if (attempts >= maxAttempts) {
|
|
396
|
+
// 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())));
|
|
399
|
+
reject(new Error(`${globalName} not found after loading script from ${url}`));
|
|
338
400
|
} else {
|
|
339
|
-
|
|
401
|
+
attempts++;
|
|
402
|
+
setTimeout(checkGlobal, checkInterval);
|
|
340
403
|
}
|
|
341
|
-
}
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
// Start checking immediately (don't wait 100ms first)
|
|
407
|
+
checkGlobal();
|
|
342
408
|
};
|
|
343
409
|
|
|
344
410
|
script.onerror = () => {
|
|
@@ -366,12 +432,12 @@ export class ComponentCompiler {
|
|
|
366
432
|
const factoryCreator = new Function(
|
|
367
433
|
'React', 'ReactDOM',
|
|
368
434
|
'useState', 'useEffect', 'useCallback', 'useMemo', 'useRef', 'useContext', 'useReducer', 'useLayoutEffect',
|
|
369
|
-
'libraries', 'styles', 'console',
|
|
435
|
+
'libraries', 'styles', 'console', 'components',
|
|
370
436
|
`${transpiledCode}; return createComponent;`
|
|
371
437
|
);
|
|
372
438
|
|
|
373
439
|
// Return a function that executes the factory with runtime context
|
|
374
|
-
return (context: RuntimeContext, styles: any = {}) => {
|
|
440
|
+
return (context: RuntimeContext, styles: any = {}, components: Record<string, any> = {}) => {
|
|
375
441
|
const { React, ReactDOM, libraries = {} } = context;
|
|
376
442
|
|
|
377
443
|
// Merge loaded libraries with context libraries
|
|
@@ -394,7 +460,8 @@ export class ComponentCompiler {
|
|
|
394
460
|
React.useLayoutEffect,
|
|
395
461
|
mergedLibraries,
|
|
396
462
|
styles,
|
|
397
|
-
console
|
|
463
|
+
console,
|
|
464
|
+
components
|
|
398
465
|
);
|
|
399
466
|
|
|
400
467
|
// Call createComponent to get the actual component
|
|
@@ -411,7 +478,8 @@ export class ComponentCompiler {
|
|
|
411
478
|
React.useLayoutEffect,
|
|
412
479
|
mergedLibraries,
|
|
413
480
|
styles,
|
|
414
|
-
console
|
|
481
|
+
console,
|
|
482
|
+
components
|
|
415
483
|
);
|
|
416
484
|
|
|
417
485
|
// Return the component directly
|
package/src/index.ts
CHANGED
|
@@ -71,10 +71,6 @@ export {
|
|
|
71
71
|
} from './runtime';
|
|
72
72
|
|
|
73
73
|
// Export utilities
|
|
74
|
-
export {
|
|
75
|
-
RuntimeUtilities,
|
|
76
|
-
createRuntimeUtilities
|
|
77
|
-
} from './utilities/runtime-utilities';
|
|
78
74
|
|
|
79
75
|
export {
|
|
80
76
|
SetupStyles,
|
|
@@ -93,6 +89,11 @@ export {
|
|
|
93
89
|
LibraryLoadResult
|
|
94
90
|
} from './utilities/library-loader';
|
|
95
91
|
|
|
92
|
+
export {
|
|
93
|
+
LibraryRegistry,
|
|
94
|
+
LibraryDefinition
|
|
95
|
+
} from './utilities/library-registry';
|
|
96
|
+
|
|
96
97
|
export {
|
|
97
98
|
ComponentErrorAnalyzer,
|
|
98
99
|
FailedComponentInfo
|
|
@@ -167,6 +167,24 @@ export class ComponentRegistry {
|
|
|
167
167
|
return components;
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
+
/**
|
|
171
|
+
* Gets all components in a namespace and version as a map
|
|
172
|
+
* @param namespace - Namespace to query (default: 'Global')
|
|
173
|
+
* @param version - Version to query (default: 'v1')
|
|
174
|
+
* @returns Object mapping component names to components
|
|
175
|
+
*/
|
|
176
|
+
getAll(namespace: string = 'Global', version: string = 'v1'): Record<string, any> {
|
|
177
|
+
const components: Record<string, any> = {};
|
|
178
|
+
|
|
179
|
+
for (const entry of this.registry.values()) {
|
|
180
|
+
if (entry.metadata.namespace === namespace && entry.metadata.version === version) {
|
|
181
|
+
components[entry.metadata.name] = entry.component;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return components;
|
|
186
|
+
}
|
|
187
|
+
|
|
170
188
|
/**
|
|
171
189
|
* Gets all registered namespaces
|
|
172
190
|
* @returns Array of unique namespace names
|
|
@@ -7,13 +7,14 @@
|
|
|
7
7
|
import {
|
|
8
8
|
CompilationResult,
|
|
9
9
|
CompileOptions,
|
|
10
|
-
ComponentStyles,
|
|
11
10
|
RuntimeContext
|
|
12
11
|
} from '../types';
|
|
13
12
|
import { ComponentCompiler } from '../compiler';
|
|
14
13
|
import { ComponentRegistry } from '../registry';
|
|
15
14
|
|
|
16
|
-
import { ComponentSpec } from '@memberjunction/interactive-component-types';
|
|
15
|
+
import { ComponentSpec, ComponentStyles } from '@memberjunction/interactive-component-types';
|
|
16
|
+
import { UserInfo } from '@memberjunction/core';
|
|
17
|
+
import { ComponentLibraryEntity } from '@memberjunction/core-entities';
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* Result of a hierarchy registration operation
|
|
@@ -48,6 +49,10 @@ export interface HierarchyRegistrationOptions {
|
|
|
48
49
|
continueOnError?: boolean;
|
|
49
50
|
/** Whether to override existing components */
|
|
50
51
|
allowOverride?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Required, metadata for all possible libraries allowed by the system
|
|
54
|
+
*/
|
|
55
|
+
allLibraries: ComponentLibraryEntity[];
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
/**
|
|
@@ -68,7 +73,7 @@ export class ComponentHierarchyRegistrar {
|
|
|
68
73
|
*/
|
|
69
74
|
async registerHierarchy(
|
|
70
75
|
rootSpec: ComponentSpec,
|
|
71
|
-
options: HierarchyRegistrationOptions
|
|
76
|
+
options: HierarchyRegistrationOptions
|
|
72
77
|
): Promise<HierarchyRegistrationResult> {
|
|
73
78
|
const {
|
|
74
79
|
styles,
|
|
@@ -78,6 +83,13 @@ export class ComponentHierarchyRegistrar {
|
|
|
78
83
|
allowOverride = true
|
|
79
84
|
} = options;
|
|
80
85
|
|
|
86
|
+
console.log('🌳 ComponentHierarchyRegistrar.registerHierarchy:', {
|
|
87
|
+
rootComponent: rootSpec.name,
|
|
88
|
+
hasLibraries: !!(rootSpec.libraries && rootSpec.libraries.length > 0),
|
|
89
|
+
libraryCount: rootSpec.libraries?.length || 0,
|
|
90
|
+
libraries: rootSpec.libraries?.map(l => l.name)
|
|
91
|
+
});
|
|
92
|
+
|
|
81
93
|
const registeredComponents: string[] = [];
|
|
82
94
|
const errors: ComponentRegistrationError[] = [];
|
|
83
95
|
const warnings: string[] = [];
|
|
@@ -85,7 +97,7 @@ export class ComponentHierarchyRegistrar {
|
|
|
85
97
|
// Register the root component
|
|
86
98
|
const rootResult = await this.registerSingleComponent(
|
|
87
99
|
rootSpec,
|
|
88
|
-
{ styles, namespace, version, allowOverride }
|
|
100
|
+
{ styles, namespace, version, allowOverride, allLibraries: options.allLibraries }
|
|
89
101
|
);
|
|
90
102
|
|
|
91
103
|
if (rootResult.success) {
|
|
@@ -102,7 +114,7 @@ export class ComponentHierarchyRegistrar {
|
|
|
102
114
|
if (childComponents.length > 0) {
|
|
103
115
|
const childResult = await this.registerChildComponents(
|
|
104
116
|
childComponents,
|
|
105
|
-
{ styles, namespace, version, continueOnError, allowOverride },
|
|
117
|
+
{ styles, namespace, version, continueOnError, allowOverride, allLibraries: options.allLibraries },
|
|
106
118
|
registeredComponents,
|
|
107
119
|
errors,
|
|
108
120
|
warnings
|
|
@@ -130,6 +142,7 @@ export class ComponentHierarchyRegistrar {
|
|
|
130
142
|
namespace?: string;
|
|
131
143
|
version?: string;
|
|
132
144
|
allowOverride?: boolean;
|
|
145
|
+
allLibraries: ComponentLibraryEntity[];
|
|
133
146
|
}
|
|
134
147
|
): Promise<{ success: boolean; error?: ComponentRegistrationError }> {
|
|
135
148
|
const { styles, namespace = 'Global', version = 'v1', allowOverride = true } = options;
|
|
@@ -161,9 +174,16 @@ export class ComponentHierarchyRegistrar {
|
|
|
161
174
|
componentName: spec.name,
|
|
162
175
|
componentCode: spec.code,
|
|
163
176
|
styles,
|
|
164
|
-
libraries: spec.libraries // Pass along library dependencies from the spec
|
|
177
|
+
libraries: spec.libraries, // Pass along library dependencies from the spec
|
|
178
|
+
dependencies: spec.dependencies, // Pass along child component dependencies
|
|
179
|
+
allLibraries: options.allLibraries
|
|
165
180
|
};
|
|
166
181
|
|
|
182
|
+
console.log(`🔧 Compiling component ${spec.name} with libraries:`, {
|
|
183
|
+
libraryCount: spec.libraries?.length || 0,
|
|
184
|
+
libraries: spec.libraries?.map(l => ({ name: l.name, globalVariable: l.globalVariable }))
|
|
185
|
+
});
|
|
186
|
+
|
|
167
187
|
const compilationResult = await this.compiler.compile(compileOptions);
|
|
168
188
|
|
|
169
189
|
if (!compilationResult.success) {
|
|
@@ -223,7 +243,8 @@ export class ComponentHierarchyRegistrar {
|
|
|
223
243
|
styles: options.styles,
|
|
224
244
|
namespace: options.namespace,
|
|
225
245
|
version: options.version,
|
|
226
|
-
allowOverride: options.allowOverride
|
|
246
|
+
allowOverride: options.allowOverride,
|
|
247
|
+
allLibraries: options.allLibraries
|
|
227
248
|
});
|
|
228
249
|
|
|
229
250
|
if (childResult.success) {
|
|
@@ -266,7 +287,7 @@ export async function registerComponentHierarchy(
|
|
|
266
287
|
compiler: ComponentCompiler,
|
|
267
288
|
registry: ComponentRegistry,
|
|
268
289
|
runtimeContext: RuntimeContext,
|
|
269
|
-
options: HierarchyRegistrationOptions
|
|
290
|
+
options: HierarchyRegistrationOptions
|
|
270
291
|
): Promise<HierarchyRegistrationResult> {
|
|
271
292
|
const registrar = new ComponentHierarchyRegistrar(compiler, registry, runtimeContext);
|
|
272
293
|
return registrar.registerHierarchy(rootSpec, options);
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* @module @memberjunction/react-runtime/runtime
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { ComponentStyles } from '@memberjunction/interactive-component-types';
|
|
8
|
+
import { ComponentProps, ComponentCallbacks } from '../types';
|
|
8
9
|
import { Subject, debounceTime, Subscription } from 'rxjs';
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -187,7 +188,7 @@ export function mergeProps(...propsList: Partial<ComponentProps>[]): ComponentPr
|
|
|
187
188
|
utilities: {},
|
|
188
189
|
callbacks: {},
|
|
189
190
|
components: {},
|
|
190
|
-
styles: {}
|
|
191
|
+
styles: {} as ComponentStyles
|
|
191
192
|
};
|
|
192
193
|
|
|
193
194
|
for (const props of propsList) {
|
package/src/types/index.ts
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
* @module @memberjunction/react-runtime/types
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { UserInfo } from '@memberjunction/core';
|
|
8
|
+
import { ComponentLibraryEntity } from '@memberjunction/core-entities';
|
|
9
|
+
import { ComponentLibraryDependency, ComponentStyles } from '@memberjunction/interactive-component-types';
|
|
10
|
+
|
|
7
11
|
/**
|
|
8
12
|
* Represents a compiled React component with its metadata
|
|
9
13
|
*/
|
|
@@ -36,22 +40,20 @@ export interface CompileOptions {
|
|
|
36
40
|
babelPlugins?: string[];
|
|
37
41
|
/** Custom Babel presets to use */
|
|
38
42
|
babelPresets?: string[];
|
|
43
|
+
|
|
39
44
|
/** Library dependencies that the component requires */
|
|
40
|
-
libraries?:
|
|
41
|
-
|
|
45
|
+
libraries?: ComponentLibraryDependency[];
|
|
46
|
+
|
|
47
|
+
/** Child component dependencies that the component requires */
|
|
48
|
+
dependencies?: Array<{ name: string; code?: string }>;
|
|
42
49
|
|
|
43
|
-
/**
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
/** CSS classes to apply */
|
|
48
|
-
className?: string;
|
|
49
|
-
/** Inline styles */
|
|
50
|
-
style?: Record<string, any>;
|
|
51
|
-
/** Global CSS to inject */
|
|
52
|
-
globalCss?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Required, metadata for all possible libraries allowed by the system
|
|
52
|
+
*/
|
|
53
|
+
allLibraries: ComponentLibraryEntity[];
|
|
53
54
|
}
|
|
54
55
|
|
|
56
|
+
|
|
55
57
|
/**
|
|
56
58
|
* Registry entry for a compiled component
|
|
57
59
|
*/
|
package/src/utilities/index.ts
CHANGED
|
@@ -99,6 +99,24 @@ export class LibraryLoader {
|
|
|
99
99
|
const ReactDOM = coreResults.find((_, i) => coreLibraries[i].globalVariable === 'ReactDOM');
|
|
100
100
|
const Babel = coreResults.find((_, i) => coreLibraries[i].globalVariable === 'Babel');
|
|
101
101
|
|
|
102
|
+
// Expose React and ReactDOM as globals for UMD libraries that expect them
|
|
103
|
+
// Many React component libraries (Recharts, Victory, etc.) expect these as globals
|
|
104
|
+
if (typeof window !== 'undefined') {
|
|
105
|
+
if (React && !(window as any).React) {
|
|
106
|
+
(window as any).React = React;
|
|
107
|
+
console.log('✓ Exposed React as window.React for UMD compatibility');
|
|
108
|
+
}
|
|
109
|
+
if (ReactDOM && !(window as any).ReactDOM) {
|
|
110
|
+
(window as any).ReactDOM = ReactDOM;
|
|
111
|
+
console.log('✓ Exposed ReactDOM as window.ReactDOM for UMD compatibility');
|
|
112
|
+
}
|
|
113
|
+
// Also expose PropTypes as empty object if not present (for older libraries)
|
|
114
|
+
if (!(window as any).PropTypes) {
|
|
115
|
+
(window as any).PropTypes = {};
|
|
116
|
+
console.log('✓ Exposed empty PropTypes as window.PropTypes for UMD compatibility');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
102
120
|
// Now load plugin libraries from configuration
|
|
103
121
|
const config = StandardLibraryManager.getConfiguration();
|
|
104
122
|
const enabledLibraries = StandardLibraryManager.getEnabledLibraries();
|