@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.
- package/.turbo/turbo-build.log +14 -16
- package/CHANGELOG.md +31 -0
- package/README.md +180 -2
- package/dist/compiler/babel-config.js.map +1 -1
- package/dist/compiler/component-compiler.d.ts.map +1 -1
- package/dist/compiler/component-compiler.js +206 -57
- package/dist/compiler/component-compiler.js.map +1 -1
- package/dist/compiler/index.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -5
- package/dist/index.js.map +1 -1
- package/dist/registry/component-registry-service.d.ts +37 -0
- package/dist/registry/component-registry-service.d.ts.map +1 -0
- package/dist/registry/component-registry-service.js +319 -0
- package/dist/registry/component-registry-service.js.map +1 -0
- package/dist/registry/component-registry.d.ts +4 -3
- package/dist/registry/component-registry.d.ts.map +1 -1
- package/dist/registry/component-registry.js.map +1 -1
- package/dist/registry/component-resolver.d.ts +12 -2
- package/dist/registry/component-resolver.d.ts.map +1 -1
- package/dist/registry/component-resolver.js +96 -12
- package/dist/registry/component-resolver.js.map +1 -1
- package/dist/registry/index.d.ts +2 -0
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +3 -1
- package/dist/registry/index.js.map +1 -1
- package/dist/registry/registry-provider.d.ts +54 -0
- package/dist/registry/registry-provider.d.ts.map +1 -0
- package/dist/registry/registry-provider.js +3 -0
- package/dist/registry/registry-provider.js.map +1 -0
- package/dist/runtime/component-hierarchy.d.ts.map +1 -1
- package/dist/runtime/component-hierarchy.js +8 -2
- package/dist/runtime/component-hierarchy.js.map +1 -1
- package/dist/runtime/error-boundary.js.map +1 -1
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/prop-builder.d.ts +2 -2
- package/dist/runtime/prop-builder.d.ts.map +1 -1
- package/dist/runtime/prop-builder.js +32 -14
- package/dist/runtime/prop-builder.js.map +1 -1
- package/dist/runtime/react-root-manager.js.map +1 -1
- package/dist/runtime.umd.js +1 -1
- package/dist/types/dependency-types.d.ts +62 -0
- package/dist/types/dependency-types.d.ts.map +1 -0
- package/dist/types/dependency-types.js +3 -0
- package/dist/types/dependency-types.js.map +1 -0
- package/dist/types/index.d.ts +8 -10
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/library-config.js.map +1 -1
- package/dist/utilities/cache-manager.js.map +1 -1
- package/dist/utilities/component-error-analyzer.js.map +1 -1
- package/dist/utilities/component-styles.js.map +1 -1
- package/dist/utilities/core-libraries.js.map +1 -1
- package/dist/utilities/index.d.ts +1 -0
- package/dist/utilities/index.d.ts.map +1 -1
- package/dist/utilities/index.js +1 -0
- package/dist/utilities/index.js.map +1 -1
- package/dist/utilities/library-dependency-resolver.d.ts +19 -0
- package/dist/utilities/library-dependency-resolver.d.ts.map +1 -0
- package/dist/utilities/library-dependency-resolver.js +410 -0
- package/dist/utilities/library-dependency-resolver.js.map +1 -0
- package/dist/utilities/library-loader.d.ts +9 -0
- package/dist/utilities/library-loader.d.ts.map +1 -1
- package/dist/utilities/library-loader.js +143 -0
- package/dist/utilities/library-loader.js.map +1 -1
- package/dist/utilities/library-registry.js.map +1 -1
- package/dist/utilities/resource-manager.js.map +1 -1
- package/dist/utilities/standard-libraries.js.map +1 -1
- package/package.json +5 -6
- package/src/compiler/component-compiler.ts +227 -77
- package/src/index.ts +21 -5
- package/src/registry/component-registry-service.ts +578 -0
- package/src/registry/component-registry.ts +8 -7
- package/src/registry/component-resolver.ts +146 -16
- package/src/registry/index.ts +9 -0
- package/src/registry/registry-provider.ts +119 -0
- package/src/runtime/component-hierarchy.ts +13 -5
- package/src/runtime/prop-builder.ts +38 -18
- package/src/types/dependency-types.ts +110 -0
- package/src/types/index.ts +17 -21
- package/src/utilities/index.ts +1 -0
- package/src/utilities/library-dependency-resolver.ts +603 -0
- package/src/utilities/library-loader.ts +252 -0
- package/tsconfig.json +2 -1
- 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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
62
|
-
|
|
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(
|
|
129
|
+
visited.add(componentId);
|
|
66
130
|
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
|
package/src/registry/index.ts
CHANGED
|
@@ -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
|
-
//
|
|
201
|
-
const
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
122
|
+
// Provide default implementations for required callbacks
|
|
123
|
+
const normalized: ComponentCallbacks = {
|
|
124
|
+
OpenEntityRecord: callbacks?.OpenEntityRecord || (() => {}),
|
|
125
|
+
RegisterMethod: callbacks?.RegisterMethod || (() => {})
|
|
126
|
+
};
|
|
125
127
|
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -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
|
-
/**
|
|
16
|
-
|
|
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:
|
|
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:
|
|
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';
|
package/src/utilities/index.ts
CHANGED
|
@@ -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';
|