@memberjunction/react-runtime 2.112.0 → 2.113.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 (43) hide show
  1. package/.turbo/turbo-build.log +11 -10
  2. package/CHANGELOG.md +15 -1
  3. package/dist/compiler/component-compiler.d.ts.map +1 -1
  4. package/dist/compiler/component-compiler.js +56 -66
  5. package/dist/compiler/component-compiler.js.map +1 -1
  6. package/dist/component-manager/component-manager.d.ts.map +1 -1
  7. package/dist/component-manager/component-manager.js +42 -48
  8. package/dist/component-manager/component-manager.js.map +1 -1
  9. package/dist/component-manager/types.d.ts +1 -1
  10. package/dist/component-manager/types.d.ts.map +1 -1
  11. package/dist/component-manager/types.js.map +1 -1
  12. package/dist/registry/component-registry-service.d.ts +1 -1
  13. package/dist/registry/component-registry-service.d.ts.map +1 -1
  14. package/dist/registry/component-registry-service.js +34 -34
  15. package/dist/registry/component-registry-service.js.map +1 -1
  16. package/dist/registry/component-resolver.d.ts +1 -1
  17. package/dist/registry/component-resolver.d.ts.map +1 -1
  18. package/dist/registry/component-resolver.js +11 -10
  19. package/dist/registry/component-resolver.js.map +1 -1
  20. package/dist/runtime/component-hierarchy.d.ts +1 -1
  21. package/dist/runtime/component-hierarchy.d.ts.map +1 -1
  22. package/dist/runtime/component-hierarchy.js +43 -43
  23. package/dist/runtime/component-hierarchy.js.map +1 -1
  24. package/dist/runtime/prop-builder.d.ts.map +1 -1
  25. package/dist/runtime/prop-builder.js +24 -22
  26. package/dist/runtime/prop-builder.js.map +1 -1
  27. package/dist/runtime.umd.js +511 -494
  28. package/dist/types/index.d.ts.map +1 -1
  29. package/dist/types/index.js.map +1 -1
  30. package/dist/utilities/library-registry.d.ts +1 -1
  31. package/dist/utilities/library-registry.d.ts.map +1 -1
  32. package/dist/utilities/library-registry.js +10 -10
  33. package/dist/utilities/library-registry.js.map +1 -1
  34. package/package.json +6 -5
  35. package/src/compiler/component-compiler.ts +164 -186
  36. package/src/component-manager/component-manager.ts +216 -162
  37. package/src/component-manager/types.ts +27 -27
  38. package/src/registry/component-registry-service.ts +218 -190
  39. package/src/registry/component-resolver.ts +98 -87
  40. package/src/runtime/component-hierarchy.ts +94 -57
  41. package/src/runtime/prop-builder.ts +33 -28
  42. package/src/types/index.ts +4 -3
  43. package/src/utilities/library-registry.ts +19 -14
@@ -9,7 +9,7 @@ import { ComponentRegistryService } from './component-registry-service';
9
9
  import { ComponentSpec } from '@memberjunction/interactive-component-types';
10
10
  import { ComponentCompiler } from '../compiler';
11
11
  import { RuntimeContext } from '../types';
12
- import { UserInfo } from '@memberjunction/global';
12
+ import { UserInfo } from '@memberjunction/core';
13
13
  import { ComponentMetadataEngine } from '@memberjunction/core-entities';
14
14
 
15
15
  /**
@@ -39,11 +39,16 @@ export class ComponentResolver {
39
39
  * @param runtimeContext - Optional runtime context for registry-based components
40
40
  * @param debug - Enable debug logging (defaults to false)
41
41
  */
42
- constructor(registry: ComponentRegistry, compiler?: ComponentCompiler, runtimeContext?: RuntimeContext, debug: boolean = false) {
42
+ constructor(
43
+ registry: ComponentRegistry,
44
+ compiler?: ComponentCompiler,
45
+ runtimeContext?: RuntimeContext,
46
+ debug: boolean = false
47
+ ) {
43
48
  this.registry = registry;
44
49
  this.resolverInstanceId = `resolver-${Date.now()}-${Math.random()}`;
45
50
  this.debug = debug;
46
-
51
+
47
52
  if (compiler && runtimeContext) {
48
53
  this.compiler = compiler;
49
54
  this.runtimeContext = runtimeContext;
@@ -58,7 +63,11 @@ export class ComponentResolver {
58
63
  * @param contextUser - Optional user context for database operations
59
64
  * @returns Map of component names to resolved components
60
65
  */
61
- async resolveComponents(spec: ComponentSpec, namespace: string = 'Global', contextUser?: UserInfo): Promise<ResolvedComponents> {
66
+ async resolveComponents(
67
+ spec: ComponentSpec,
68
+ namespace: string = 'Global',
69
+ contextUser?: UserInfo
70
+ ): Promise<ResolvedComponents> {
62
71
  console.log(`🚀 [ComponentResolver] Starting component resolution for: ${spec.name}`);
63
72
  console.log(`📋 [ComponentResolver] Root component spec:`, {
64
73
  name: spec.name,
@@ -66,22 +75,19 @@ export class ComponentResolver {
66
75
  registry: spec.registry,
67
76
  namespace: spec.namespace,
68
77
  hasCode: !!spec.code,
69
- hasDependencies: !!(spec.dependencies && spec.dependencies.length > 0),
78
+ hasDependencies: !!(spec.dependencies && spec.dependencies.length > 0)
70
79
  });
71
-
80
+
72
81
  if (this.debug) {
73
- console.log(
74
- `📋 [ComponentResolver] Dependencies to resolve:`,
75
- (spec.dependencies || []).map((d) => ({
76
- name: d.name,
77
- location: d.location,
78
- namespace: d.namespace,
79
- }))
80
- );
82
+ console.log(`📋 [ComponentResolver] Dependencies to resolve:`, (spec.dependencies || []).map(d => ({
83
+ name: d.name,
84
+ location: d.location,
85
+ namespace: d.namespace
86
+ })));
81
87
  }
82
-
88
+
83
89
  const resolved: ResolvedComponents = {};
84
-
90
+
85
91
  // Initialize component engine if we have registry service
86
92
  if (this.registryService) {
87
93
  if (this.debug) {
@@ -92,22 +98,22 @@ export class ComponentResolver {
92
98
  console.log(`✅ [ComponentResolver] Component engine initialized with ${this.componentEngine.Components?.length || 0} components`);
93
99
  }
94
100
  }
95
-
101
+
96
102
  // Resolve the component hierarchy
97
103
  console.log(`🔄 [ComponentResolver] About to call resolveComponentHierarchy for root: ${spec.name}`);
98
104
  await this.resolveComponentHierarchy(spec, resolved, namespace, new Set(), contextUser);
99
105
  console.log(`✅ [ComponentResolver] Returned from resolveComponentHierarchy`);
100
106
  console.log(`🔍 [ComponentResolver] Looking for root component '${spec.name}' in resolved:`, !!resolved[spec.name]);
101
-
107
+
102
108
  if (!resolved[spec.name]) {
103
109
  console.error(`❌ [ComponentResolver] Root component '${spec.name}' was NOT added to resolved map!`);
104
110
  console.log(`📦 [ComponentResolver] What IS in resolved map:`, Object.keys(resolved));
105
111
  }
106
-
112
+
107
113
  if (this.debug) {
108
114
  console.log(`📊 [ComponentResolver] Resolved components before unwrapping:`, Object.keys(resolved));
109
115
  }
110
-
116
+
111
117
  // Unwrap component wrappers before returning
112
118
  // Components from the registry come as objects with component/print/refresh properties
113
119
  // We need to extract just the component function for use in child components
@@ -137,18 +143,15 @@ export class ComponentResolver {
137
143
  unwrapped[name] = value; // Pass through for debugging
138
144
  }
139
145
  }
140
-
146
+
141
147
  if (this.debug) {
142
- console.log(
143
- `🎯 [ComponentResolver] Final resolved components:`,
144
- Object.keys(unwrapped).map((name) => ({
145
- name,
146
- type: typeof unwrapped[name],
147
- isUndefined: unwrapped[name] === undefined,
148
- }))
149
- );
148
+ console.log(`🎯 [ComponentResolver] Final resolved components:`, Object.keys(unwrapped).map(name => ({
149
+ name,
150
+ type: typeof unwrapped[name],
151
+ isUndefined: unwrapped[name] === undefined
152
+ })));
150
153
  }
151
-
154
+
152
155
  return unwrapped;
153
156
  }
154
157
 
@@ -169,7 +172,7 @@ export class ComponentResolver {
169
172
  ): Promise<void> {
170
173
  // Create a unique identifier for this component
171
174
  const componentId = `${spec.namespace || namespace}/${spec.name}@${spec.version || 'latest'}`;
172
-
175
+
173
176
  // Check if already resolved (not just visited)
174
177
  if (resolved[spec.name]) {
175
178
  if (this.debug) {
@@ -177,7 +180,7 @@ export class ComponentResolver {
177
180
  }
178
181
  return;
179
182
  }
180
-
183
+
181
184
  // Prevent circular dependencies
182
185
  if (visited.has(componentId)) {
183
186
  if (this.debug) {
@@ -214,7 +217,7 @@ export class ComponentResolver {
214
217
  console.log(` 📍 [ComponentResolver] Local registry (no registry field specified)`);
215
218
  }
216
219
  }
217
-
220
+
218
221
  try {
219
222
  // If spec.registry is populated, this is an external registry component
220
223
  // If spec.registry is blank/undefined, this is a local registry component
@@ -223,17 +226,17 @@ export class ComponentResolver {
223
226
  if (this.debug) {
224
227
  console.log(`🌐 [ComponentResolver] Fetching from external registry: ${spec.registry}`);
225
228
  }
226
-
229
+
227
230
  // Get compiled component from registry service (which will handle the external fetch)
228
231
  const compiledComponent = await this.registryService.getCompiledComponentFromRegistry(
229
- spec.registry, // Registry name
232
+ spec.registry, // Registry name
230
233
  spec.namespace || namespace,
231
234
  spec.name,
232
235
  spec.version || 'latest',
233
236
  this.resolverInstanceId,
234
237
  contextUser
235
238
  );
236
-
239
+
237
240
  if (compiledComponent) {
238
241
  resolved[spec.name] = compiledComponent;
239
242
  if (this.debug) {
@@ -247,54 +250,54 @@ export class ComponentResolver {
247
250
  if (this.debug) {
248
251
  console.log(`💾 [ComponentResolver] Looking for locally registered component`);
249
252
  }
250
-
253
+
251
254
  // First, try to find the component in the metadata engine
252
255
  const allComponents = this.componentEngine.Components || [];
253
256
  if (this.debug) {
254
257
  console.log(`📊 [ComponentResolver] Total components in engine: ${allComponents.length}`);
255
258
  }
256
-
259
+
257
260
  // Log all matching names to see duplicates
258
261
  const matchingNames = allComponents.filter((c: any) => c.Name === spec.name);
259
262
  if (matchingNames.length > 0 && this.debug) {
260
- console.log(
261
- `🔎 [ComponentResolver] Found ${matchingNames.length} components with name "${spec.name}":`,
263
+ console.log(`🔎 [ComponentResolver] Found ${matchingNames.length} components with name "${spec.name}":`,
262
264
  matchingNames.map((c: any) => ({
263
265
  ID: c.ID,
264
266
  Name: c.Name,
265
267
  Namespace: c.Namespace,
266
268
  Version: c.Version,
267
- Status: c.Status,
269
+ Status: c.Status
268
270
  }))
269
271
  );
270
272
  }
271
-
273
+
272
274
  const component = this.componentEngine.Components?.find(
273
- (c: any) => c.Name === spec.name && c.Namespace === (spec.namespace || namespace)
275
+ (c: any) => c.Name === spec.name &&
276
+ c.Namespace === (spec.namespace || namespace)
274
277
  );
275
-
278
+
276
279
  if (component) {
277
280
  if (this.debug) {
278
281
  console.log(`✅ [ComponentResolver] Found component in local DB:`, {
279
282
  ID: component.ID,
280
283
  Name: component.Name,
281
284
  Namespace: component.Namespace,
282
- Version: component.Version,
285
+ Version: component.Version
283
286
  });
284
287
  }
285
-
288
+
286
289
  // Get compiled component from registry service (local compilation)
287
- const compiledComponent = await this.registryService.getCompiledComponent(component.ID, this.resolverInstanceId, contextUser);
290
+ const compiledComponent = await this.registryService.getCompiledComponent(
291
+ component.ID,
292
+ this.resolverInstanceId,
293
+ contextUser
294
+ );
288
295
  resolved[spec.name] = compiledComponent;
289
296
  if (this.debug) {
290
- console.log(
291
- `📦 [ComponentResolver] Successfully compiled and resolved local component: ${spec.name}, type: ${typeof compiledComponent}`
292
- );
297
+ console.log(`📦 [ComponentResolver] Successfully compiled and resolved local component: ${spec.name}, type: ${typeof compiledComponent}`);
293
298
  }
294
299
  } else {
295
- console.error(
296
- `❌ [ComponentResolver] Local registry component NOT found in database: ${spec.name} with namespace: ${spec.namespace || namespace}`
297
- );
300
+ console.error(`❌ [ComponentResolver] Local registry component NOT found in database: ${spec.name} with namespace: ${spec.namespace || namespace}`);
298
301
  if (this.debug) {
299
302
  console.warn(`Local registry component not found in database: ${spec.name}`);
300
303
  }
@@ -309,13 +312,13 @@ export class ComponentResolver {
309
312
  // Embedded/Local component
310
313
  // Use the component's specified namespace if it has one, otherwise use parent's namespace
311
314
  const componentNamespace = spec.namespace || namespace;
312
-
315
+
313
316
  // First check if component has inline code that needs compilation
314
317
  if (spec.code && this.compiler) {
315
318
  if (this.debug) {
316
319
  console.log(`🔨 [ComponentResolver] Component ${spec.name} has inline code, compiling...`);
317
320
  }
318
-
321
+
319
322
  try {
320
323
  // Compile the component with its code
321
324
  const compilationResult = await this.compiler.compile({
@@ -323,9 +326,9 @@ export class ComponentResolver {
323
326
  componentCode: spec.code,
324
327
  libraries: spec.libraries,
325
328
  dependencies: spec.dependencies,
326
- allLibraries: [], // TODO: Get from ComponentMetadataEngine if needed
329
+ allLibraries: [] // TODO: Get from ComponentMetadataEngine if needed
327
330
  });
328
-
331
+
329
332
  if (compilationResult.success && compilationResult.component) {
330
333
  // Get the component object from the factory (only if we have runtimeContext)
331
334
  if (!this.runtimeContext) {
@@ -333,13 +336,13 @@ export class ComponentResolver {
333
336
  return;
334
337
  }
335
338
  const componentObject = compilationResult.component.factory(this.runtimeContext);
336
-
339
+
337
340
  // Register it in the local registry for future use
338
341
  this.registry.register(spec.name, componentObject, componentNamespace, spec.version || 'latest');
339
-
342
+
340
343
  // Add to resolved
341
344
  resolved[spec.name] = componentObject;
342
-
345
+
343
346
  if (this.debug) {
344
347
  console.log(`✅ [ComponentResolver] Successfully compiled and registered inline component: ${spec.name}`);
345
348
  }
@@ -354,7 +357,7 @@ export class ComponentResolver {
354
357
  if (this.debug) {
355
358
  console.log(`🔍 [ComponentResolver] Looking for embedded component: ${spec.name} in namespace: ${componentNamespace}`);
356
359
  }
357
-
360
+
358
361
  const component = this.registry.get(spec.name, componentNamespace);
359
362
  if (component) {
360
363
  resolved[spec.name] = component;
@@ -373,21 +376,14 @@ export class ComponentResolver {
373
376
  if (fallbackComponent) {
374
377
  resolved[spec.name] = fallbackComponent;
375
378
  if (this.debug) {
376
- console.log(
377
- `✅ [ComponentResolver] Found embedded component in fallback namespace: ${spec.name}, type: ${typeof fallbackComponent}`
378
- );
379
+ console.log(`✅ [ComponentResolver] Found embedded component in fallback namespace: ${spec.name}, type: ${typeof fallbackComponent}`);
379
380
  }
380
381
  if (this.debug) {
381
- console.log(
382
- `📄 Resolved embedded component: ${spec.name} from fallback namespace ${namespace}, type:`,
383
- typeof fallbackComponent
384
- );
382
+ console.log(`📄 Resolved embedded component: ${spec.name} from fallback namespace ${namespace}, type:`, typeof fallbackComponent);
385
383
  }
386
384
  } else {
387
385
  // Component not found - this might cause issues later
388
- console.error(
389
- `❌ [ComponentResolver] Could not resolve embedded component: ${spec.name} in namespace ${componentNamespace} or ${namespace}`
390
- );
386
+ console.error(`❌ [ComponentResolver] Could not resolve embedded component: ${spec.name} in namespace ${componentNamespace} or ${namespace}`);
391
387
  if (this.debug) {
392
388
  console.warn(`⚠️ Could not resolve embedded component: ${spec.name} in namespace ${componentNamespace} or ${namespace}`);
393
389
  }
@@ -397,7 +393,7 @@ export class ComponentResolver {
397
393
  }
398
394
  }
399
395
  }
400
-
396
+
401
397
  // Child components have already been processed at the beginning of this method
402
398
  // No need to process them again - we're using depth-first, post-order traversal
403
399
  }
@@ -425,9 +421,9 @@ export class ComponentResolver {
425
421
  validateDependencies(spec: ComponentSpec, namespace: string = 'Global'): string[] {
426
422
  const missing: string[] = [];
427
423
  const checked = new Set<string>();
428
-
424
+
429
425
  this.checkDependencies(spec, namespace, missing, checked);
430
-
426
+
431
427
  return missing;
432
428
  }
433
429
 
@@ -438,7 +434,12 @@ export class ComponentResolver {
438
434
  * @param missing - Array to collect missing components
439
435
  * @param checked - Set of already checked components
440
436
  */
441
- private checkDependencies(spec: ComponentSpec, namespace: string, missing: string[], checked: Set<string>): void {
437
+ private checkDependencies(
438
+ spec: ComponentSpec,
439
+ namespace: string,
440
+ missing: string[],
441
+ checked: Set<string>
442
+ ): void {
442
443
  if (checked.has(spec.name)) return;
443
444
  checked.add(spec.name);
444
445
 
@@ -462,9 +463,9 @@ export class ComponentResolver {
462
463
  getDependencyGraph(spec: ComponentSpec): Map<string, string[]> {
463
464
  const graph = new Map<string, string[]>();
464
465
  const visited = new Set<string>();
465
-
466
+
466
467
  this.buildDependencyGraph(spec, graph, visited);
467
-
468
+
468
469
  return graph;
469
470
  }
470
471
 
@@ -474,13 +475,17 @@ export class ComponentResolver {
474
475
  * @param graph - Graph to build
475
476
  * @param visited - Set of visited components
476
477
  */
477
- private buildDependencyGraph(spec: ComponentSpec, graph: Map<string, string[]>, visited: Set<string>): void {
478
+ private buildDependencyGraph(
479
+ spec: ComponentSpec,
480
+ graph: Map<string, string[]>,
481
+ visited: Set<string>
482
+ ): void {
478
483
  if (visited.has(spec.name)) return;
479
484
  visited.add(spec.name);
480
485
 
481
486
  const children = spec.dependencies || [];
482
- const dependencies = children.map((child) => child.name);
483
-
487
+ const dependencies = children.map(child => child.name);
488
+
484
489
  graph.set(spec.name, dependencies);
485
490
 
486
491
  // Recursively process children
@@ -517,7 +522,12 @@ export class ComponentResolver {
517
522
  * @param visited - Set of visited nodes
518
523
  * @param stack - Result stack
519
524
  */
520
- private topologicalSortDFS(node: string, graph: Map<string, string[]>, visited: Set<string>, stack: string[]): void {
525
+ private topologicalSortDFS(
526
+ node: string,
527
+ graph: Map<string, string[]>,
528
+ visited: Set<string>,
529
+ stack: string[]
530
+ ): void {
521
531
  visited.add(node);
522
532
 
523
533
  const dependencies = graph.get(node) || [];
@@ -536,10 +546,7 @@ export class ComponentResolver {
536
546
  * @param namespace - Namespace for resolution
537
547
  * @returns Ordered array of resolved components
538
548
  */
539
- resolveInOrder(
540
- spec: ComponentSpec,
541
- namespace: string = 'Global'
542
- ): Array<{
549
+ resolveInOrder(spec: ComponentSpec, namespace: string = 'Global'): Array<{
543
550
  name: string;
544
551
  component: any;
545
552
  }> {
@@ -576,7 +583,11 @@ export class ComponentResolver {
576
583
  * @param collected - Array to collect specs
577
584
  * @param visited - Set of visited component names
578
585
  */
579
- private collectComponentSpecs(spec: ComponentSpec, collected: ComponentSpec[], visited: Set<string>): void {
586
+ private collectComponentSpecs(
587
+ spec: ComponentSpec,
588
+ collected: ComponentSpec[],
589
+ visited: Set<string>
590
+ ): void {
580
591
  if (visited.has(spec.name)) return;
581
592
  visited.add(spec.name);
582
593
 
@@ -587,4 +598,4 @@ export class ComponentResolver {
587
598
  this.collectComponentSpecs(child, collected, visited);
588
599
  }
589
600
  }
590
- }
601
+ }