@memberjunction/react-runtime 2.92.0 → 2.94.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 (87) hide show
  1. package/.turbo/turbo-build.log +14 -16
  2. package/CHANGELOG.md +31 -0
  3. package/README.md +180 -2
  4. package/dist/compiler/babel-config.js.map +1 -1
  5. package/dist/compiler/component-compiler.d.ts.map +1 -1
  6. package/dist/compiler/component-compiler.js +206 -57
  7. package/dist/compiler/component-compiler.js.map +1 -1
  8. package/dist/compiler/index.js.map +1 -1
  9. package/dist/index.d.ts +2 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +14 -5
  12. package/dist/index.js.map +1 -1
  13. package/dist/registry/component-registry-service.d.ts +37 -0
  14. package/dist/registry/component-registry-service.d.ts.map +1 -0
  15. package/dist/registry/component-registry-service.js +319 -0
  16. package/dist/registry/component-registry-service.js.map +1 -0
  17. package/dist/registry/component-registry.d.ts +4 -3
  18. package/dist/registry/component-registry.d.ts.map +1 -1
  19. package/dist/registry/component-registry.js.map +1 -1
  20. package/dist/registry/component-resolver.d.ts +12 -2
  21. package/dist/registry/component-resolver.d.ts.map +1 -1
  22. package/dist/registry/component-resolver.js +96 -12
  23. package/dist/registry/component-resolver.js.map +1 -1
  24. package/dist/registry/index.d.ts +2 -0
  25. package/dist/registry/index.d.ts.map +1 -1
  26. package/dist/registry/index.js +3 -1
  27. package/dist/registry/index.js.map +1 -1
  28. package/dist/registry/registry-provider.d.ts +54 -0
  29. package/dist/registry/registry-provider.d.ts.map +1 -0
  30. package/dist/registry/registry-provider.js +3 -0
  31. package/dist/registry/registry-provider.js.map +1 -0
  32. package/dist/runtime/component-hierarchy.d.ts.map +1 -1
  33. package/dist/runtime/component-hierarchy.js +8 -2
  34. package/dist/runtime/component-hierarchy.js.map +1 -1
  35. package/dist/runtime/error-boundary.js.map +1 -1
  36. package/dist/runtime/index.js.map +1 -1
  37. package/dist/runtime/prop-builder.d.ts +2 -2
  38. package/dist/runtime/prop-builder.d.ts.map +1 -1
  39. package/dist/runtime/prop-builder.js +32 -14
  40. package/dist/runtime/prop-builder.js.map +1 -1
  41. package/dist/runtime/react-root-manager.js.map +1 -1
  42. package/dist/runtime.umd.js +1 -1
  43. package/dist/types/dependency-types.d.ts +62 -0
  44. package/dist/types/dependency-types.d.ts.map +1 -0
  45. package/dist/types/dependency-types.js +3 -0
  46. package/dist/types/dependency-types.js.map +1 -0
  47. package/dist/types/index.d.ts +8 -10
  48. package/dist/types/index.d.ts.map +1 -1
  49. package/dist/types/index.js +1 -0
  50. package/dist/types/index.js.map +1 -1
  51. package/dist/types/library-config.js.map +1 -1
  52. package/dist/utilities/cache-manager.js.map +1 -1
  53. package/dist/utilities/component-error-analyzer.js.map +1 -1
  54. package/dist/utilities/component-styles.js.map +1 -1
  55. package/dist/utilities/core-libraries.js.map +1 -1
  56. package/dist/utilities/index.d.ts +1 -0
  57. package/dist/utilities/index.d.ts.map +1 -1
  58. package/dist/utilities/index.js +1 -0
  59. package/dist/utilities/index.js.map +1 -1
  60. package/dist/utilities/library-dependency-resolver.d.ts +19 -0
  61. package/dist/utilities/library-dependency-resolver.d.ts.map +1 -0
  62. package/dist/utilities/library-dependency-resolver.js +410 -0
  63. package/dist/utilities/library-dependency-resolver.js.map +1 -0
  64. package/dist/utilities/library-loader.d.ts +9 -0
  65. package/dist/utilities/library-loader.d.ts.map +1 -1
  66. package/dist/utilities/library-loader.js +143 -0
  67. package/dist/utilities/library-loader.js.map +1 -1
  68. package/dist/utilities/library-registry.js.map +1 -1
  69. package/dist/utilities/resource-manager.js.map +1 -1
  70. package/dist/utilities/standard-libraries.js.map +1 -1
  71. package/package.json +5 -6
  72. package/src/compiler/component-compiler.ts +227 -77
  73. package/src/index.ts +21 -5
  74. package/src/registry/component-registry-service.ts +578 -0
  75. package/src/registry/component-registry.ts +8 -7
  76. package/src/registry/component-resolver.ts +146 -16
  77. package/src/registry/index.ts +9 -0
  78. package/src/registry/registry-provider.ts +119 -0
  79. package/src/runtime/component-hierarchy.ts +13 -5
  80. package/src/runtime/prop-builder.ts +38 -18
  81. package/src/types/dependency-types.ts +110 -0
  82. package/src/types/index.ts +17 -21
  83. package/src/utilities/index.ts +1 -0
  84. package/src/utilities/library-dependency-resolver.ts +603 -0
  85. package/src/utilities/library-loader.ts +252 -0
  86. package/tsconfig.json +2 -1
  87. package/tsconfig.tsbuildinfo +0 -1
@@ -5,7 +5,12 @@
5
5
  */
6
6
 
7
7
  import { ComponentRegistry } from './component-registry';
8
+ import { ComponentRegistryService } from './component-registry-service';
8
9
  import { ComponentSpec } from '@memberjunction/interactive-component-types';
10
+ import { ComponentCompiler } from '../compiler';
11
+ import { RuntimeContext } from '../types';
12
+ import { UserInfo } from '@memberjunction/core';
13
+ import { ComponentMetadataEngine } from '@memberjunction/core-entities';
9
14
 
10
15
  /**
11
16
  * Resolved component map for passing to React components
@@ -20,28 +25,80 @@ export interface ResolvedComponents {
20
25
  */
21
26
  export class ComponentResolver {
22
27
  private registry: ComponentRegistry;
28
+ private registryService: ComponentRegistryService | null = null;
29
+ private resolverInstanceId: string;
30
+ private compiler: ComponentCompiler | null = null;
31
+ private runtimeContext: RuntimeContext | null = null;
32
+ private componentEngine = ComponentMetadataEngine.Instance;
33
+ private debug: boolean = false;
23
34
 
24
35
  /**
25
36
  * Creates a new ComponentResolver instance
26
37
  * @param registry - Component registry to use for resolution
38
+ * @param compiler - Optional compiler for registry-based components
39
+ * @param runtimeContext - Optional runtime context for registry-based components
40
+ * @param debug - Enable debug logging (defaults to false)
27
41
  */
28
- constructor(registry: ComponentRegistry) {
42
+ constructor(
43
+ registry: ComponentRegistry,
44
+ compiler?: ComponentCompiler,
45
+ runtimeContext?: RuntimeContext,
46
+ debug: boolean = false
47
+ ) {
29
48
  this.registry = registry;
49
+ this.resolverInstanceId = `resolver-${Date.now()}-${Math.random()}`;
50
+ this.debug = debug;
51
+
52
+ if (compiler && runtimeContext) {
53
+ this.compiler = compiler;
54
+ this.runtimeContext = runtimeContext;
55
+ this.registryService = ComponentRegistryService.getInstance(compiler, runtimeContext, debug);
56
+ }
30
57
  }
31
58
 
32
59
  /**
33
60
  * Resolves all components for a given component specification
34
61
  * @param spec - Root component specification
35
62
  * @param namespace - Namespace for component resolution
63
+ * @param contextUser - Optional user context for database operations
36
64
  * @returns Map of component names to resolved components
37
65
  */
38
- resolveComponents(spec: ComponentSpec, namespace: string = 'Global'): ResolvedComponents {
66
+ async resolveComponents(
67
+ spec: ComponentSpec,
68
+ namespace: string = 'Global',
69
+ contextUser?: UserInfo
70
+ ): Promise<ResolvedComponents> {
39
71
  const resolved: ResolvedComponents = {};
40
72
 
73
+ // Initialize component engine if we have registry service
74
+ if (this.registryService) {
75
+ await this.componentEngine.Config(false, contextUser);
76
+ }
77
+
41
78
  // Resolve the component hierarchy
42
- this.resolveComponentHierarchy(spec, resolved, namespace);
79
+ await this.resolveComponentHierarchy(spec, resolved, namespace, new Set(), contextUser);
43
80
 
44
- return resolved;
81
+ // Unwrap component wrappers before returning
82
+ // Components from the registry come as objects with component/print/refresh properties
83
+ // We need to extract just the component function for use in child components
84
+ const unwrapped: ResolvedComponents = {};
85
+ for (const [name, value] of Object.entries(resolved)) {
86
+ if (value && typeof value === 'object' && 'component' in value) {
87
+ if (typeof value.component === 'function') {
88
+ // This is a wrapped component - extract the actual React component function
89
+ unwrapped[name] = value.component;
90
+ } else {
91
+ // ComponentObject has a component property but it's not a function
92
+ console.error(`Component ${name} has invalid component property:`, typeof value.component, value);
93
+ unwrapped[name] = value; // Pass through the problematic value so we can see the error
94
+ }
95
+ } else {
96
+ // This is already a plain component function or something else
97
+ unwrapped[name] = value;
98
+ }
99
+ }
100
+
101
+ return unwrapped;
45
102
  }
46
103
 
47
104
  /**
@@ -50,30 +107,103 @@ export class ComponentResolver {
50
107
  * @param resolved - Map to store resolved components
51
108
  * @param namespace - Namespace for resolution
52
109
  * @param visited - Set of visited component names to prevent cycles
110
+ * @param contextUser - Optional user context for database operations
53
111
  */
54
- private resolveComponentHierarchy(
112
+ private async resolveComponentHierarchy(
55
113
  spec: ComponentSpec,
56
114
  resolved: ResolvedComponents,
57
115
  namespace: string,
58
- visited: Set<string> = new Set()
59
- ): void {
116
+ visited: Set<string> = new Set(),
117
+ contextUser?: UserInfo
118
+ ): Promise<void> {
119
+ // Create a unique identifier for this component
120
+ const componentId = `${spec.namespace || namespace}/${spec.name}@${spec.version || 'latest'}`;
121
+
60
122
  // Prevent circular dependencies
61
- if (visited.has(spec.name)) {
62
- console.warn(`Circular dependency detected for component: ${spec.name}`);
123
+ if (visited.has(componentId)) {
124
+ if (this.debug) {
125
+ console.warn(`Circular dependency detected for component: ${componentId}`);
126
+ }
63
127
  return;
64
128
  }
65
- visited.add(spec.name);
129
+ visited.add(componentId);
66
130
 
67
- // Try to get component from registry
68
- const component = this.registry.get(spec.name, namespace);
69
- if (component) {
70
- resolved[spec.name] = component;
131
+ // Handle based on location
132
+ if (spec.location === 'registry' && this.registryService) {
133
+ // Registry component - need to load from database or external source
134
+ try {
135
+ // First, try to find the component in the metadata engine
136
+ const component = this.componentEngine.Components?.find(
137
+ (c: any) => c.Name === spec.name &&
138
+ c.Namespace === (spec.namespace || namespace)
139
+ );
140
+
141
+ if (component) {
142
+ // Get compiled component from registry service
143
+ const compiledComponent = await this.registryService.getCompiledComponent(
144
+ component.ID,
145
+ this.resolverInstanceId,
146
+ contextUser
147
+ );
148
+ resolved[spec.name] = compiledComponent;
149
+ if (this.debug) {
150
+ console.log(`📦 Resolved registry component: ${spec.name} from ${componentId}`);
151
+ }
152
+ } else {
153
+ if (this.debug) {
154
+ console.warn(`Registry component not found in database: ${spec.name}`);
155
+ }
156
+ }
157
+ } catch (error) {
158
+ if (this.debug) {
159
+ console.error(`Failed to load registry component ${spec.name}:`, error);
160
+ }
161
+ }
162
+ } else {
163
+ // Embedded component - get from local registry
164
+ // Use the component's specified namespace if it has one, otherwise use parent's namespace
165
+ const componentNamespace = spec.namespace || namespace;
166
+ const component = this.registry.get(spec.name, componentNamespace);
167
+ if (component) {
168
+ resolved[spec.name] = component;
169
+ if (this.debug) {
170
+ console.log(`📄 Resolved embedded component: ${spec.name} from namespace ${componentNamespace}, type:`, typeof component);
171
+ }
172
+ } else {
173
+ // If not found with specified namespace, try the parent namespace as fallback
174
+ const fallbackComponent = this.registry.get(spec.name, namespace);
175
+ if (fallbackComponent) {
176
+ resolved[spec.name] = fallbackComponent;
177
+ if (this.debug) {
178
+ console.log(`📄 Resolved embedded component: ${spec.name} from fallback namespace ${namespace}, type:`, typeof fallbackComponent);
179
+ }
180
+ } else {
181
+ // Component not found - this might cause issues later
182
+ console.warn(`⚠️ Could not resolve embedded component: ${spec.name} in namespace ${componentNamespace} or ${namespace}`);
183
+ // Store undefined explicitly so we know it failed to resolve
184
+ resolved[spec.name] = undefined;
185
+ }
186
+ }
71
187
  }
72
188
 
73
- // Process child components
189
+ // Process child components recursively
74
190
  const children = spec.dependencies || [];
75
191
  for (const child of children) {
76
- this.resolveComponentHierarchy(child, resolved, namespace, visited);
192
+ await this.resolveComponentHierarchy(child, resolved, namespace, visited, contextUser);
193
+ }
194
+ }
195
+
196
+ /**
197
+ * Cleanup resolver resources
198
+ */
199
+ cleanup(): void {
200
+ // Remove our references when resolver is destroyed
201
+ if (this.registryService) {
202
+ // This would allow the registry service to clean up unused components
203
+ // Implementation would track which components this resolver referenced
204
+ if (this.debug) {
205
+ console.log(`Cleaning up resolver: ${this.resolverInstanceId}`);
206
+ }
77
207
  }
78
208
  }
79
209
 
@@ -5,4 +5,13 @@
5
5
 
6
6
  export { ComponentRegistry } from './component-registry';
7
7
  export { ComponentResolver, ResolvedComponents } from './component-resolver';
8
+ export { ComponentRegistryService } from './component-registry-service';
9
+ export {
10
+ RegistryProvider,
11
+ RegistryComponentMetadata,
12
+ RegistryComponentResponse,
13
+ RegistrySearchFilters,
14
+ ComponentDependencyInfo,
15
+ DependencyTree
16
+ } from './registry-provider';
8
17
  export { ComponentSpec } from '@memberjunction/interactive-component-types';
@@ -0,0 +1,119 @@
1
+ /**
2
+ * @fileoverview Registry provider interfaces and implementations for component loading
3
+ * @module @memberjunction/react-runtime/registry
4
+ */
5
+
6
+ import { ComponentSpec } from '@memberjunction/interactive-component-types';
7
+
8
+ /**
9
+ * Metadata about a component from a registry
10
+ */
11
+ export interface RegistryComponentMetadata {
12
+ name: string;
13
+ namespace: string;
14
+ version: string;
15
+ description: string;
16
+ title?: string;
17
+ type?: string;
18
+ status?: string;
19
+ properties?: ComponentSpec['properties'];
20
+ events?: ComponentSpec['events'];
21
+ libraries?: ComponentSpec['libraries'];
22
+ dependencies?: ComponentSpec['dependencies'];
23
+ sourceRegistryID?: string | null;
24
+ isLocal: boolean;
25
+ lastFetched?: Date;
26
+ cacheDuration?: number;
27
+ }
28
+
29
+ /**
30
+ * Response from fetching a component from a registry
31
+ */
32
+ export interface RegistryComponentResponse {
33
+ metadata: RegistryComponentMetadata;
34
+ spec: ComponentSpec;
35
+ }
36
+
37
+ /**
38
+ * Interface for registry providers that can fetch components
39
+ */
40
+ export interface RegistryProvider {
41
+ /**
42
+ * Name of the registry provider
43
+ */
44
+ name: string;
45
+
46
+ /**
47
+ * Fetch a component from the registry
48
+ * @param name - Component name
49
+ * @param namespace - Component namespace
50
+ * @param version - Component version (optional, defaults to latest)
51
+ * @returns Component metadata and specification
52
+ */
53
+ fetchComponent(
54
+ name: string,
55
+ namespace: string,
56
+ version?: string
57
+ ): Promise<RegistryComponentResponse>;
58
+
59
+ /**
60
+ * Check if a component exists in the registry
61
+ * @param name - Component name
62
+ * @param namespace - Component namespace
63
+ * @param version - Component version (optional)
64
+ * @returns True if component exists
65
+ */
66
+ componentExists?(
67
+ name: string,
68
+ namespace: string,
69
+ version?: string
70
+ ): Promise<boolean>;
71
+
72
+ /**
73
+ * Get available versions of a component
74
+ * @param name - Component name
75
+ * @param namespace - Component namespace
76
+ * @returns Array of available versions
77
+ */
78
+ getComponentVersions?(
79
+ name: string,
80
+ namespace: string
81
+ ): Promise<string[]>;
82
+ }
83
+
84
+ /**
85
+ * Search filters for registry queries
86
+ */
87
+ export interface RegistrySearchFilters {
88
+ type?: string;
89
+ status?: string;
90
+ namespace?: string;
91
+ query?: string;
92
+ limit?: number;
93
+ offset?: number;
94
+ }
95
+
96
+ /**
97
+ * Dependency information for a component
98
+ */
99
+ export interface ComponentDependencyInfo {
100
+ name: string;
101
+ namespace: string;
102
+ version?: string;
103
+ isRequired: boolean;
104
+ location: 'embedded' | 'registry';
105
+ sourceRegistryID?: string | null;
106
+ }
107
+
108
+ /**
109
+ * Tree structure for dependency resolution
110
+ */
111
+ export interface DependencyTree {
112
+ componentId: string;
113
+ name?: string;
114
+ namespace?: string;
115
+ version?: string;
116
+ dependencies?: DependencyTree[];
117
+ circular?: boolean;
118
+ totalCount?: number;
119
+ }
@@ -197,14 +197,22 @@ export class ComponentHierarchyRegistrar {
197
197
  };
198
198
  }
199
199
 
200
- // Create component factory
201
- const componentFactory = compilationResult.component!.component(this.runtimeContext, styles);
200
+ // 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
209
+ });
202
210
 
203
- // Register the component
211
+ // Register the full ComponentObject (not just the React component)
204
212
  this.registry.register(
205
213
  spec.name,
206
- componentFactory.component,
207
- namespace,
214
+ componentObject,
215
+ spec.namespace || namespace,
208
216
  version
209
217
  );
210
218
 
@@ -4,8 +4,8 @@
4
4
  * @module @memberjunction/react-runtime/runtime
5
5
  */
6
6
 
7
- import { ComponentStyles } from '@memberjunction/interactive-component-types';
8
- import { ComponentProps, ComponentCallbacks } from '../types';
7
+ import { ComponentStyles, ComponentCallbacks } from '@memberjunction/interactive-component-types';
8
+ import { ComponentProps } from '../types';
9
9
  import { Subject, debounceTime, Subscription } from 'rxjs';
10
10
 
11
11
  /**
@@ -39,7 +39,10 @@ export function buildComponentProps(
39
39
  data: any = {},
40
40
  userState: any = {},
41
41
  utilities: any = {},
42
- callbacks: ComponentCallbacks = {},
42
+ callbacks: ComponentCallbacks = {
43
+ OpenEntityRecord: () => {},
44
+ RegisterMethod: () => {}
45
+ },
43
46
  components: Record<string, any> = {},
44
47
  styles?: ComponentStyles,
45
48
  options: PropBuilderOptions = {},
@@ -116,15 +119,19 @@ function deepEqual(obj1: any, obj2: any): boolean {
116
119
  * @returns Normalized callbacks
117
120
  */
118
121
  export function normalizeCallbacks(callbacks: any, debounceMs: number = 3000): ComponentCallbacks {
119
- const normalized: ComponentCallbacks = {};
120
-
121
- // Ensure all callbacks are functions
122
- if (callbacks.RefreshData && typeof callbacks.RefreshData === 'function') {
123
- normalized.RefreshData = callbacks.RefreshData;
124
- }
122
+ // Provide default implementations for required callbacks
123
+ const normalized: ComponentCallbacks = {
124
+ OpenEntityRecord: callbacks?.OpenEntityRecord || (() => {}),
125
+ RegisterMethod: callbacks?.RegisterMethod || (() => {})
126
+ };
125
127
 
126
- if (callbacks.OpenEntityRecord && typeof callbacks.OpenEntityRecord === 'function') {
127
- normalized.OpenEntityRecord = callbacks.OpenEntityRecord;
128
+ // Copy any additional callbacks that might exist
129
+ if (callbacks) {
130
+ Object.keys(callbacks).forEach(key => {
131
+ if (typeof callbacks[key] === 'function' && !normalized.hasOwnProperty(key)) {
132
+ (normalized as any)[key] = callbacks[key];
133
+ }
134
+ });
128
135
  }
129
136
 
130
137
  return normalized;
@@ -264,14 +271,20 @@ export function wrapCallbacksWithLogging(
264
271
  callbacks: ComponentCallbacks,
265
272
  componentName: string
266
273
  ): ComponentCallbacks {
267
- const wrapped: ComponentCallbacks = {};
274
+ const wrapped: ComponentCallbacks = {
275
+ OpenEntityRecord: callbacks?.OpenEntityRecord || (() => {}),
276
+ RegisterMethod: callbacks?.RegisterMethod || (() => {})
277
+ };
268
278
 
269
- if (callbacks.RefreshData) {
270
- wrapped.RefreshData = () => {
271
- console.log(`[${componentName}] RefreshData called`);
272
- callbacks.RefreshData!();
273
- };
274
- }
279
+ // Wrap any additional callbacks that might exist
280
+ Object.keys(callbacks).forEach(key => {
281
+ if (key !== 'OpenEntityRecord' && key !== 'RegisterMethod' && typeof (callbacks as any)[key] === 'function') {
282
+ (wrapped as any)[key] = (...args: any[]) => {
283
+ console.log(`[${componentName}] ${key} called with args:`, args);
284
+ return (callbacks as any)[key](...args);
285
+ };
286
+ }
287
+ });
275
288
 
276
289
  if (callbacks.OpenEntityRecord) {
277
290
  wrapped.OpenEntityRecord = (entityName: string, key: any) => {
@@ -280,6 +293,13 @@ export function wrapCallbacksWithLogging(
280
293
  };
281
294
  }
282
295
 
296
+ if (callbacks.RegisterMethod) {
297
+ wrapped.RegisterMethod = (methodName: any, handler: any) => {
298
+ console.log(`[${componentName}] RegisterMethod called for:`, methodName);
299
+ callbacks.RegisterMethod!(methodName, handler);
300
+ };
301
+ }
302
+
283
303
  return wrapped;
284
304
  }
285
305
 
@@ -0,0 +1,110 @@
1
+ /**
2
+ * @fileoverview Type definitions for library dependency management
3
+ * @module @memberjunction/react-runtime/types
4
+ */
5
+
6
+ import { ComponentLibraryEntity } from '@memberjunction/core-entities';
7
+
8
+ /**
9
+ * Represents a parsed dependency with name and version specification
10
+ */
11
+ export interface ParsedDependency {
12
+ name: string;
13
+ versionSpec: string;
14
+ }
15
+
16
+ /**
17
+ * Represents a version requirement for a library
18
+ */
19
+ export interface VersionRequirement {
20
+ library: string;
21
+ versionSpec: string;
22
+ requestedBy: string; // Which library requested this dependency
23
+ }
24
+
25
+ /**
26
+ * Represents a resolved version after conflict resolution
27
+ */
28
+ export interface ResolvedVersion {
29
+ library: string;
30
+ version: string;
31
+ satisfies: VersionRequirement[];
32
+ warnings?: string[];
33
+ }
34
+
35
+ /**
36
+ * Node in the dependency graph
37
+ */
38
+ export interface DependencyNode {
39
+ library: ComponentLibraryEntity;
40
+ dependencies: Map<string, string>; // dependency name -> version spec
41
+ dependents: Set<string>; // libraries that depend on this one
42
+ }
43
+
44
+ /**
45
+ * Dependency graph structure
46
+ */
47
+ export interface DependencyGraph {
48
+ nodes: Map<string, DependencyNode>;
49
+ roots: Set<string>; // libraries with no dependents
50
+ }
51
+
52
+ /**
53
+ * Result of determining load order
54
+ */
55
+ export interface LoadOrderResult {
56
+ success: boolean;
57
+ order?: ComponentLibraryEntity[];
58
+ cycles?: string[][];
59
+ errors?: string[];
60
+ warnings?: string[];
61
+ }
62
+
63
+ /**
64
+ * Semver version range types
65
+ */
66
+ export type VersionRangeType = 'exact' | 'tilde' | 'caret' | 'range' | 'any';
67
+
68
+ /**
69
+ * Parsed semver version
70
+ */
71
+ export interface ParsedVersion {
72
+ major: number;
73
+ minor: number;
74
+ patch: number;
75
+ prerelease?: string;
76
+ build?: string;
77
+ }
78
+
79
+ /**
80
+ * Version range specification
81
+ */
82
+ export interface VersionRange {
83
+ type: VersionRangeType;
84
+ operator?: string;
85
+ version?: ParsedVersion;
86
+ raw: string;
87
+ }
88
+
89
+ /**
90
+ * Library load state tracking
91
+ */
92
+ export interface LoadedLibraryState {
93
+ name: string;
94
+ version: string;
95
+ globalVariable: string;
96
+ loadedAt: Date;
97
+ requestedBy: string[];
98
+ dependencies: string[];
99
+ }
100
+
101
+ /**
102
+ * Options for dependency resolution
103
+ */
104
+ export interface DependencyResolutionOptions {
105
+ allowPrerelease?: boolean;
106
+ preferLatest?: boolean;
107
+ strict?: boolean; // Fail on any version conflict
108
+ maxDepth?: number; // Maximum dependency depth to prevent infinite recursion
109
+ debug?: boolean;
110
+ }
@@ -6,14 +6,14 @@
6
6
 
7
7
  import { UserInfo } from '@memberjunction/core';
8
8
  import { ComponentLibraryEntity } from '@memberjunction/core-entities';
9
- import { ComponentLibraryDependency, ComponentStyles } from '@memberjunction/interactive-component-types';
9
+ import { ComponentLibraryDependency, ComponentStyles, ComponentObject } from '@memberjunction/interactive-component-types';
10
10
 
11
11
  /**
12
12
  * Represents a compiled React component with its metadata
13
13
  */
14
14
  export interface CompiledComponent {
15
- /** The compiled React component function or class */
16
- component: any;
15
+ /** Factory function that creates a ComponentObject when called with context */
16
+ factory: (context: RuntimeContext, styles?: ComponentStyles) => ComponentObject;
17
17
  /** Unique identifier for the component */
18
18
  id: string;
19
19
  /** Original component name */
@@ -58,8 +58,8 @@ export interface CompileOptions {
58
58
  * Registry entry for a compiled component
59
59
  */
60
60
  export interface RegistryEntry {
61
- /** The compiled component */
62
- component: any;
61
+ /** The compiled component object with all methods */
62
+ component: ComponentObject;
63
63
  /** Component metadata */
64
64
  metadata: ComponentMetadata;
65
65
  /** Last access time for LRU cache */
@@ -113,7 +113,7 @@ export interface ComponentProps {
113
113
  /** Utility functions available to the component */
114
114
  utilities: any;
115
115
  /** Callback functions */
116
- callbacks: ComponentCallbacks;
116
+ callbacks: any;
117
117
  /** Child components available for use */
118
118
  components?: Record<string, any>;
119
119
  /** Component styles */
@@ -122,20 +122,6 @@ export interface ComponentProps {
122
122
  onStateChanged?: (stateUpdate: Record<string, any>) => void;
123
123
  }
124
124
 
125
- /**
126
- * Callbacks available to React components
127
- */
128
- export interface ComponentCallbacks {
129
- /** Request data refresh */
130
- RefreshData?: () => void;
131
- /** Open an entity record */
132
- OpenEntityRecord?: (entityName: string, key: any) => void;
133
- /** Update user state */
134
- UpdateUserState?: (state: any) => void;
135
- /** Notify of a custom event */
136
- NotifyEvent?: (event: string, data: any) => void;
137
- }
138
-
139
125
  /**
140
126
  * Configuration for the component compiler
141
127
  */
@@ -155,6 +141,8 @@ export interface CompilerConfig {
155
141
  cache: boolean;
156
142
  /** Maximum cache size */
157
143
  maxCacheSize: number;
144
+ /** Enable debug logging */
145
+ debug?: boolean;
158
146
  }
159
147
 
160
148
  /**
@@ -169,6 +157,8 @@ export interface RegistryConfig {
169
157
  useLRU: boolean;
170
158
  /** Namespace isolation */
171
159
  enableNamespaces: boolean;
160
+ /** Enable debug logging */
161
+ debug?: boolean;
172
162
  }
173
163
 
174
164
  /**
@@ -232,4 +222,10 @@ export interface ErrorBoundaryOptions {
232
222
  }
233
223
 
234
224
  // Export library configuration types
235
- export * from './library-config';
225
+ export * from './library-config';
226
+
227
+ // Export dependency types
228
+ export * from './dependency-types';
229
+
230
+ // Re-export ComponentObject for convenience
231
+ export { ComponentObject } from '@memberjunction/interactive-component-types';
@@ -7,6 +7,7 @@ export * from './component-styles';
7
7
  export * from './standard-libraries';
8
8
  export * from './library-loader';
9
9
  export * from './library-registry';
10
+ export * from './library-dependency-resolver';
10
11
  export * from './component-error-analyzer';
11
12
  export * from './resource-manager';
12
13
  export * from './cache-manager';