@memberjunction/react-runtime 2.111.0 → 2.112.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 +10 -11
- package/CHANGELOG.md +6 -6
- package/dist/compiler/component-compiler.d.ts.map +1 -1
- package/dist/compiler/component-compiler.js +66 -56
- package/dist/compiler/component-compiler.js.map +1 -1
- package/dist/component-manager/component-manager.d.ts.map +1 -1
- package/dist/component-manager/component-manager.js +48 -42
- package/dist/component-manager/component-manager.js.map +1 -1
- package/dist/component-manager/types.d.ts +1 -1
- package/dist/component-manager/types.d.ts.map +1 -1
- package/dist/component-manager/types.js.map +1 -1
- package/dist/registry/component-registry-service.d.ts +1 -1
- package/dist/registry/component-registry-service.d.ts.map +1 -1
- package/dist/registry/component-registry-service.js +34 -34
- package/dist/registry/component-registry-service.js.map +1 -1
- package/dist/registry/component-resolver.d.ts +1 -1
- package/dist/registry/component-resolver.d.ts.map +1 -1
- package/dist/registry/component-resolver.js +10 -11
- package/dist/registry/component-resolver.js.map +1 -1
- package/dist/runtime/component-hierarchy.d.ts +1 -1
- package/dist/runtime/component-hierarchy.d.ts.map +1 -1
- package/dist/runtime/component-hierarchy.js +43 -43
- package/dist/runtime/component-hierarchy.js.map +1 -1
- package/dist/runtime/prop-builder.d.ts.map +1 -1
- package/dist/runtime/prop-builder.js +22 -24
- package/dist/runtime/prop-builder.js.map +1 -1
- package/dist/runtime.umd.js +494 -511
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utilities/library-registry.d.ts +1 -1
- package/dist/utilities/library-registry.d.ts.map +1 -1
- package/dist/utilities/library-registry.js +10 -10
- package/dist/utilities/library-registry.js.map +1 -1
- package/package.json +5 -6
- package/src/compiler/component-compiler.ts +186 -164
- package/src/component-manager/component-manager.ts +162 -216
- package/src/component-manager/types.ts +27 -27
- package/src/registry/component-registry-service.ts +190 -218
- package/src/registry/component-resolver.ts +87 -98
- package/src/runtime/component-hierarchy.ts +57 -94
- package/src/runtime/prop-builder.ts +28 -33
- package/src/types/index.ts +3 -4
- package/src/utilities/library-registry.ts +14 -19
|
@@ -4,17 +4,12 @@
|
|
|
4
4
|
* @module @memberjunction/react-runtime/hierarchy
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
CompilationResult,
|
|
9
|
-
CompileOptions,
|
|
10
|
-
RuntimeContext,
|
|
11
|
-
CompiledComponent
|
|
12
|
-
} from '../types';
|
|
7
|
+
import { CompilationResult, CompileOptions, RuntimeContext, CompiledComponent } from '../types';
|
|
13
8
|
import { ComponentCompiler } from '../compiler';
|
|
14
9
|
import { ComponentRegistry } from '../registry';
|
|
15
10
|
|
|
16
11
|
import { ComponentSpec, ComponentStyles } from '@memberjunction/interactive-component-types';
|
|
17
|
-
import { UserInfo, Metadata, LogStatus, GetProductionStatus } from '@memberjunction/
|
|
12
|
+
import { UserInfo, Metadata, LogStatus, GetProductionStatus } from '@memberjunction/global';
|
|
18
13
|
import { ComponentLibraryEntity } from '@memberjunction/core-entities';
|
|
19
14
|
|
|
20
15
|
/**
|
|
@@ -70,30 +65,27 @@ export class ComponentHierarchyRegistrar {
|
|
|
70
65
|
private registry: ComponentRegistry,
|
|
71
66
|
private runtimeContext: RuntimeContext
|
|
72
67
|
) {}
|
|
73
|
-
|
|
68
|
+
|
|
74
69
|
/**
|
|
75
70
|
* Fetches a component specification from an external registry
|
|
76
71
|
*/
|
|
77
|
-
private async fetchExternalComponent(
|
|
78
|
-
spec: ComponentSpec,
|
|
79
|
-
contextUser?: UserInfo
|
|
80
|
-
): Promise<ComponentSpec | null> {
|
|
72
|
+
private async fetchExternalComponent(spec: ComponentSpec, contextUser?: UserInfo): Promise<ComponentSpec | null> {
|
|
81
73
|
try {
|
|
82
74
|
const provider = Metadata?.Provider;
|
|
83
75
|
if (!provider || !(provider as any).ExecuteGQL) {
|
|
84
76
|
console.warn('⚠️ [ComponentHierarchyRegistrar] No GraphQL provider available for external registry fetch');
|
|
85
77
|
return null;
|
|
86
78
|
}
|
|
87
|
-
|
|
79
|
+
|
|
88
80
|
// Dynamically import the GraphQL client to avoid circular dependencies
|
|
89
81
|
const { GraphQLComponentRegistryClient } = await import('@memberjunction/graphql-dataprovider');
|
|
90
82
|
const graphQLClient = new GraphQLComponentRegistryClient(provider as any);
|
|
91
|
-
|
|
83
|
+
|
|
92
84
|
const fullSpec = await graphQLClient.GetRegistryComponent({
|
|
93
85
|
registryName: spec.registry!,
|
|
94
86
|
namespace: spec.namespace || 'Global',
|
|
95
87
|
name: spec.name,
|
|
96
|
-
version: spec.version || 'latest'
|
|
88
|
+
version: spec.version || 'latest',
|
|
97
89
|
});
|
|
98
90
|
|
|
99
91
|
if (fullSpec && fullSpec.code) {
|
|
@@ -117,25 +109,16 @@ export class ComponentHierarchyRegistrar {
|
|
|
117
109
|
* @param options - Registration options
|
|
118
110
|
* @returns Registration result with details about success/failures
|
|
119
111
|
*/
|
|
120
|
-
async registerHierarchy(
|
|
121
|
-
rootSpec: ComponentSpec,
|
|
122
|
-
options: HierarchyRegistrationOptions
|
|
123
|
-
): Promise<HierarchyRegistrationResult> {
|
|
112
|
+
async registerHierarchy(rootSpec: ComponentSpec, options: HierarchyRegistrationOptions): Promise<HierarchyRegistrationResult> {
|
|
124
113
|
// If this is an external registry component without code, fetch it first
|
|
125
114
|
let resolvedRootSpec = rootSpec;
|
|
126
115
|
if (rootSpec.location === 'registry' && rootSpec.registry && !rootSpec.code) {
|
|
127
116
|
if (!GetProductionStatus()) {
|
|
128
117
|
LogStatus(`🌐 [ComponentHierarchyRegistrar] Fetching external registry component: ${rootSpec.registry}/${rootSpec.name}`);
|
|
129
118
|
}
|
|
130
|
-
resolvedRootSpec = await this.fetchExternalComponent(rootSpec, options.contextUser) || rootSpec;
|
|
119
|
+
resolvedRootSpec = (await this.fetchExternalComponent(rootSpec, options.contextUser)) || rootSpec;
|
|
131
120
|
}
|
|
132
|
-
const {
|
|
133
|
-
styles,
|
|
134
|
-
namespace = 'Global',
|
|
135
|
-
version = 'v1',
|
|
136
|
-
continueOnError = true,
|
|
137
|
-
allowOverride = true
|
|
138
|
-
} = options;
|
|
121
|
+
const { styles, namespace = 'Global', version = 'v1', continueOnError = true, allowOverride = true } = options;
|
|
139
122
|
|
|
140
123
|
const registeredComponents: string[] = [];
|
|
141
124
|
const errors: ComponentRegistrationError[] = [];
|
|
@@ -145,7 +128,7 @@ export class ComponentHierarchyRegistrar {
|
|
|
145
128
|
LogStatus('🌳 ComponentHierarchyRegistrar.registerHierarchy:', undefined, {
|
|
146
129
|
rootComponent: resolvedRootSpec.name,
|
|
147
130
|
hasLibraries: !!(resolvedRootSpec.libraries && resolvedRootSpec.libraries.length > 0),
|
|
148
|
-
libraryCount: resolvedRootSpec.libraries?.length || 0
|
|
131
|
+
libraryCount: resolvedRootSpec.libraries?.length || 0,
|
|
149
132
|
});
|
|
150
133
|
}
|
|
151
134
|
|
|
@@ -153,34 +136,34 @@ export class ComponentHierarchyRegistrar {
|
|
|
153
136
|
const compiledMap = new Map<string, CompiledComponent>();
|
|
154
137
|
const specMap = new Map<string, ComponentSpec>();
|
|
155
138
|
const allLoadedLibraries = new Map<string, any>(); // Track all loaded libraries
|
|
156
|
-
|
|
139
|
+
|
|
157
140
|
// Helper to compile a component without calling its factory
|
|
158
141
|
const compileOnly = async (spec: ComponentSpec): Promise<{ success: boolean; error?: ComponentRegistrationError }> => {
|
|
159
142
|
if (!spec.code) return { success: true };
|
|
160
|
-
|
|
143
|
+
|
|
161
144
|
try {
|
|
162
145
|
// Filter out invalid library entries before compilation
|
|
163
|
-
const validLibraries = spec.libraries?.filter(lib => {
|
|
146
|
+
const validLibraries = spec.libraries?.filter((lib) => {
|
|
164
147
|
if (!lib || typeof lib !== 'object') return false;
|
|
165
148
|
if (!lib.name || lib.name === 'unknown' || lib.name === 'null' || lib.name === 'undefined') return false;
|
|
166
149
|
if (!lib.globalVariable || lib.globalVariable === 'undefined' || lib.globalVariable === 'null') return false;
|
|
167
150
|
return true;
|
|
168
151
|
});
|
|
169
|
-
|
|
152
|
+
|
|
170
153
|
const compileOptions: CompileOptions = {
|
|
171
154
|
componentName: spec.name,
|
|
172
155
|
componentCode: spec.code,
|
|
173
156
|
styles,
|
|
174
157
|
libraries: validLibraries,
|
|
175
158
|
dependencies: spec.dependencies,
|
|
176
|
-
allLibraries: options.allLibraries
|
|
159
|
+
allLibraries: options.allLibraries,
|
|
177
160
|
};
|
|
178
|
-
|
|
161
|
+
|
|
179
162
|
const result = await this.compiler.compile(compileOptions);
|
|
180
163
|
if (result.success && result.component) {
|
|
181
164
|
compiledMap.set(spec.name, result.component);
|
|
182
165
|
specMap.set(spec.name, spec);
|
|
183
|
-
|
|
166
|
+
|
|
184
167
|
// Extract and accumulate loaded libraries from the compilation
|
|
185
168
|
if (result.loadedLibraries) {
|
|
186
169
|
result.loadedLibraries.forEach((value, key) => {
|
|
@@ -192,7 +175,7 @@ export class ComponentHierarchyRegistrar {
|
|
|
192
175
|
}
|
|
193
176
|
});
|
|
194
177
|
}
|
|
195
|
-
|
|
178
|
+
|
|
196
179
|
return { success: true };
|
|
197
180
|
} else {
|
|
198
181
|
return {
|
|
@@ -200,8 +183,8 @@ export class ComponentHierarchyRegistrar {
|
|
|
200
183
|
error: {
|
|
201
184
|
componentName: spec.name,
|
|
202
185
|
error: result.error?.message || 'Unknown compilation error',
|
|
203
|
-
phase: 'compilation'
|
|
204
|
-
}
|
|
186
|
+
phase: 'compilation',
|
|
187
|
+
},
|
|
205
188
|
};
|
|
206
189
|
}
|
|
207
190
|
} catch (error) {
|
|
@@ -210,21 +193,21 @@ export class ComponentHierarchyRegistrar {
|
|
|
210
193
|
error: {
|
|
211
194
|
componentName: spec.name,
|
|
212
195
|
error: error instanceof Error ? error.message : String(error),
|
|
213
|
-
phase: 'compilation'
|
|
214
|
-
}
|
|
196
|
+
phase: 'compilation',
|
|
197
|
+
},
|
|
215
198
|
};
|
|
216
199
|
}
|
|
217
200
|
};
|
|
218
|
-
|
|
201
|
+
|
|
219
202
|
// Compile all components in hierarchy
|
|
220
203
|
const compileQueue = [resolvedRootSpec];
|
|
221
204
|
const visited = new Set<string>();
|
|
222
|
-
|
|
205
|
+
|
|
223
206
|
while (compileQueue.length > 0) {
|
|
224
207
|
let spec = compileQueue.shift()!;
|
|
225
208
|
if (visited.has(spec.name)) continue;
|
|
226
209
|
visited.add(spec.name);
|
|
227
|
-
|
|
210
|
+
|
|
228
211
|
// If this is an external registry component without code, fetch it first
|
|
229
212
|
if (spec.location === 'registry' && spec.registry && !spec.code) {
|
|
230
213
|
const fetched = await this.fetchExternalComponent(spec, options.contextUser);
|
|
@@ -235,7 +218,7 @@ export class ComponentHierarchyRegistrar {
|
|
|
235
218
|
continue;
|
|
236
219
|
}
|
|
237
220
|
}
|
|
238
|
-
|
|
221
|
+
|
|
239
222
|
const result = await compileOnly(spec);
|
|
240
223
|
if (!result.success) {
|
|
241
224
|
errors.push(result.error!);
|
|
@@ -243,12 +226,12 @@ export class ComponentHierarchyRegistrar {
|
|
|
243
226
|
return { success: false, registeredComponents, errors, warnings, resolvedSpec: resolvedRootSpec };
|
|
244
227
|
}
|
|
245
228
|
}
|
|
246
|
-
|
|
229
|
+
|
|
247
230
|
if (spec.dependencies) {
|
|
248
231
|
compileQueue.push(...spec.dependencies);
|
|
249
232
|
}
|
|
250
233
|
}
|
|
251
|
-
|
|
234
|
+
|
|
252
235
|
// Add all accumulated libraries to runtime context
|
|
253
236
|
if (allLoadedLibraries.size > 0) {
|
|
254
237
|
if (!this.runtimeContext.libraries) {
|
|
@@ -261,11 +244,11 @@ export class ComponentHierarchyRegistrar {
|
|
|
261
244
|
}
|
|
262
245
|
});
|
|
263
246
|
}
|
|
264
|
-
|
|
247
|
+
|
|
265
248
|
// PHASE 2: Execute all factories with components available
|
|
266
249
|
for (const [name, compiled] of compiledMap) {
|
|
267
250
|
const spec = specMap.get(name)!;
|
|
268
|
-
|
|
251
|
+
|
|
269
252
|
// Build components object from all registered components
|
|
270
253
|
const components: Record<string, any> = {};
|
|
271
254
|
for (const [depName, depCompiled] of compiledMap) {
|
|
@@ -273,18 +256,13 @@ export class ComponentHierarchyRegistrar {
|
|
|
273
256
|
const depObject = depCompiled.factory(this.runtimeContext, styles);
|
|
274
257
|
components[depName] = depObject.component;
|
|
275
258
|
}
|
|
276
|
-
|
|
259
|
+
|
|
277
260
|
// Now call factory with components available
|
|
278
261
|
const componentObject = compiled.factory(this.runtimeContext, styles, components);
|
|
279
|
-
|
|
262
|
+
|
|
280
263
|
// Register in registry
|
|
281
|
-
this.registry.register(
|
|
282
|
-
|
|
283
|
-
componentObject,
|
|
284
|
-
spec.namespace || namespace,
|
|
285
|
-
version
|
|
286
|
-
);
|
|
287
|
-
|
|
264
|
+
this.registry.register(spec.name, componentObject, spec.namespace || namespace, version);
|
|
265
|
+
|
|
288
266
|
registeredComponents.push(spec.name);
|
|
289
267
|
}
|
|
290
268
|
|
|
@@ -293,7 +271,7 @@ export class ComponentHierarchyRegistrar {
|
|
|
293
271
|
registeredComponents,
|
|
294
272
|
errors,
|
|
295
273
|
warnings,
|
|
296
|
-
resolvedSpec: resolvedRootSpec
|
|
274
|
+
resolvedSpec: resolvedRootSpec,
|
|
297
275
|
};
|
|
298
276
|
}
|
|
299
277
|
|
|
@@ -320,7 +298,7 @@ export class ComponentHierarchyRegistrar {
|
|
|
320
298
|
if (!spec.code) {
|
|
321
299
|
return {
|
|
322
300
|
success: true,
|
|
323
|
-
error: undefined
|
|
301
|
+
error: undefined,
|
|
324
302
|
};
|
|
325
303
|
}
|
|
326
304
|
|
|
@@ -332,13 +310,13 @@ export class ComponentHierarchyRegistrar {
|
|
|
332
310
|
error: {
|
|
333
311
|
componentName: spec.name,
|
|
334
312
|
error: `Component already registered in ${namespace}/${version}`,
|
|
335
|
-
phase: 'registration'
|
|
336
|
-
}
|
|
313
|
+
phase: 'registration',
|
|
314
|
+
},
|
|
337
315
|
};
|
|
338
316
|
}
|
|
339
317
|
|
|
340
318
|
// Filter out invalid library entries before compilation
|
|
341
|
-
const validLibraries = spec.libraries?.filter(lib => {
|
|
319
|
+
const validLibraries = spec.libraries?.filter((lib) => {
|
|
342
320
|
if (!lib || typeof lib !== 'object') return false;
|
|
343
321
|
if (!lib.name || lib.name === 'unknown' || lib.name === 'null' || lib.name === 'undefined') return false;
|
|
344
322
|
if (!lib.globalVariable || lib.globalVariable === 'undefined' || lib.globalVariable === 'null') return false;
|
|
@@ -349,7 +327,7 @@ export class ComponentHierarchyRegistrar {
|
|
|
349
327
|
LogStatus(`🔧 Compiling component ${spec.name} with libraries:`, undefined, {
|
|
350
328
|
originalCount: spec.libraries?.length || 0,
|
|
351
329
|
filteredCount: validLibraries?.length || 0,
|
|
352
|
-
libraries: validLibraries?.map(l => l.name) || []
|
|
330
|
+
libraries: validLibraries?.map((l) => l.name) || [],
|
|
353
331
|
});
|
|
354
332
|
}
|
|
355
333
|
|
|
@@ -360,7 +338,7 @@ export class ComponentHierarchyRegistrar {
|
|
|
360
338
|
styles,
|
|
361
339
|
libraries: validLibraries, // Pass along filtered library dependencies
|
|
362
340
|
dependencies: spec.dependencies, // Pass along child component dependencies
|
|
363
|
-
allLibraries: options.allLibraries
|
|
341
|
+
allLibraries: options.allLibraries,
|
|
364
342
|
};
|
|
365
343
|
|
|
366
344
|
const compilationResult = await this.compiler.compile(compileOptions);
|
|
@@ -371,8 +349,8 @@ export class ComponentHierarchyRegistrar {
|
|
|
371
349
|
error: {
|
|
372
350
|
componentName: spec.name,
|
|
373
351
|
error: compilationResult.error?.message || 'Unknown compilation error',
|
|
374
|
-
phase: 'compilation'
|
|
375
|
-
}
|
|
352
|
+
phase: 'compilation',
|
|
353
|
+
},
|
|
376
354
|
};
|
|
377
355
|
}
|
|
378
356
|
|
|
@@ -396,29 +374,23 @@ export class ComponentHierarchyRegistrar {
|
|
|
396
374
|
LogStatus(`🏭 Calling factory for ${spec.name} with runtime context:`, undefined, {
|
|
397
375
|
hasReact: !!this.runtimeContext.React,
|
|
398
376
|
hasReactDOM: !!this.runtimeContext.ReactDOM,
|
|
399
|
-
libraryCount: Object.keys(this.runtimeContext.libraries || {}).length
|
|
377
|
+
libraryCount: Object.keys(this.runtimeContext.libraries || {}).length,
|
|
400
378
|
});
|
|
401
379
|
}
|
|
402
380
|
const componentObject = compilationResult.component!.factory(this.runtimeContext, styles);
|
|
403
381
|
|
|
404
382
|
// Register the full ComponentObject (not just the React component)
|
|
405
|
-
this.registry.register(
|
|
406
|
-
spec.name,
|
|
407
|
-
componentObject,
|
|
408
|
-
spec.namespace || namespace,
|
|
409
|
-
version
|
|
410
|
-
);
|
|
383
|
+
this.registry.register(spec.name, componentObject, spec.namespace || namespace, version);
|
|
411
384
|
|
|
412
385
|
return { success: true };
|
|
413
|
-
|
|
414
386
|
} catch (error) {
|
|
415
387
|
return {
|
|
416
388
|
success: false,
|
|
417
389
|
error: {
|
|
418
390
|
componentName: spec.name,
|
|
419
391
|
error: error instanceof Error ? error.message : String(error),
|
|
420
|
-
phase: 'registration'
|
|
421
|
-
}
|
|
392
|
+
phase: 'registration',
|
|
393
|
+
},
|
|
422
394
|
};
|
|
423
395
|
}
|
|
424
396
|
}
|
|
@@ -445,7 +417,7 @@ export class ComponentHierarchyRegistrar {
|
|
|
445
417
|
namespace: options.namespace,
|
|
446
418
|
version: options.version,
|
|
447
419
|
allowOverride: options.allowOverride,
|
|
448
|
-
allLibraries: options.allLibraries
|
|
420
|
+
allLibraries: options.allLibraries,
|
|
449
421
|
});
|
|
450
422
|
|
|
451
423
|
if (childResult.success) {
|
|
@@ -462,13 +434,7 @@ export class ComponentHierarchyRegistrar {
|
|
|
462
434
|
// Register nested children recursively
|
|
463
435
|
const nestedChildren = child.dependencies || [];
|
|
464
436
|
if (nestedChildren.length > 0) {
|
|
465
|
-
await this.registerChildComponents(
|
|
466
|
-
nestedChildren,
|
|
467
|
-
options,
|
|
468
|
-
registeredComponents,
|
|
469
|
-
errors,
|
|
470
|
-
warnings
|
|
471
|
-
);
|
|
437
|
+
await this.registerChildComponents(nestedChildren, options, registeredComponents, errors, warnings);
|
|
472
438
|
}
|
|
473
439
|
}
|
|
474
440
|
}
|
|
@@ -520,7 +486,7 @@ export function validateComponentSpec(spec: ComponentSpec): string[] {
|
|
|
520
486
|
const children = spec.dependencies || [];
|
|
521
487
|
children.forEach((child, index) => {
|
|
522
488
|
const childErrors = validateComponentSpec(child);
|
|
523
|
-
childErrors.forEach(error => {
|
|
489
|
+
childErrors.forEach((error) => {
|
|
524
490
|
errors.push(`Child ${index} (${child.name || 'unnamed'}): ${error}`);
|
|
525
491
|
});
|
|
526
492
|
});
|
|
@@ -535,9 +501,9 @@ export function validateComponentSpec(spec: ComponentSpec): string[] {
|
|
|
535
501
|
*/
|
|
536
502
|
export function flattenComponentHierarchy(rootSpec: ComponentSpec): ComponentSpec[] {
|
|
537
503
|
const components: ComponentSpec[] = [rootSpec];
|
|
538
|
-
|
|
504
|
+
|
|
539
505
|
const children = rootSpec.dependencies || [];
|
|
540
|
-
children.forEach(child => {
|
|
506
|
+
children.forEach((child) => {
|
|
541
507
|
components.push(...flattenComponentHierarchy(child));
|
|
542
508
|
});
|
|
543
509
|
|
|
@@ -550,20 +516,17 @@ export function flattenComponentHierarchy(rootSpec: ComponentSpec): ComponentSpe
|
|
|
550
516
|
* @param includeEmpty - Whether to include components without code
|
|
551
517
|
* @returns Total component count
|
|
552
518
|
*/
|
|
553
|
-
export function countComponentsInHierarchy(
|
|
554
|
-
rootSpec: ComponentSpec,
|
|
555
|
-
includeEmpty: boolean = false
|
|
556
|
-
): number {
|
|
519
|
+
export function countComponentsInHierarchy(rootSpec: ComponentSpec, includeEmpty: boolean = false): number {
|
|
557
520
|
let count = 0;
|
|
558
|
-
|
|
521
|
+
|
|
559
522
|
if (includeEmpty || rootSpec.code) {
|
|
560
523
|
count = 1;
|
|
561
524
|
}
|
|
562
525
|
|
|
563
526
|
const children = rootSpec.dependencies || [];
|
|
564
|
-
children.forEach(child => {
|
|
527
|
+
children.forEach((child) => {
|
|
565
528
|
count += countComponentsInHierarchy(child, includeEmpty);
|
|
566
529
|
});
|
|
567
530
|
|
|
568
531
|
return count;
|
|
569
|
-
}
|
|
532
|
+
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { ComponentStyles, ComponentCallbacks } from '@memberjunction/interactive-component-types';
|
|
8
8
|
import { ComponentProps } from '../types';
|
|
9
9
|
import { Subject, debounceTime, Subscription } from 'rxjs';
|
|
10
|
-
import { LogStatus, GetProductionStatus } from '@memberjunction/
|
|
10
|
+
import { LogStatus, GetProductionStatus } from '@memberjunction/global';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Options for building component props
|
|
@@ -43,7 +43,7 @@ export function buildComponentProps(
|
|
|
43
43
|
callbacks: ComponentCallbacks = {
|
|
44
44
|
OpenEntityRecord: () => {},
|
|
45
45
|
RegisterMethod: () => {},
|
|
46
|
-
CreateSimpleNotification: () => {}
|
|
46
|
+
CreateSimpleNotification: () => {},
|
|
47
47
|
},
|
|
48
48
|
components: Record<string, any> = {},
|
|
49
49
|
styles?: ComponentStyles,
|
|
@@ -54,7 +54,7 @@ export function buildComponentProps(
|
|
|
54
54
|
validate = true,
|
|
55
55
|
transformData,
|
|
56
56
|
transformState,
|
|
57
|
-
debounceUpdateUserState = 3000 // Default 3 seconds
|
|
57
|
+
debounceUpdateUserState = 3000, // Default 3 seconds
|
|
58
58
|
} = options;
|
|
59
59
|
|
|
60
60
|
// Transform data if transformer provided
|
|
@@ -69,7 +69,7 @@ export function buildComponentProps(
|
|
|
69
69
|
callbacks: normalizeCallbacks(callbacks, debounceUpdateUserState),
|
|
70
70
|
components,
|
|
71
71
|
styles: normalizeStyles(styles),
|
|
72
|
-
onStateChanged
|
|
72
|
+
onStateChanged,
|
|
73
73
|
};
|
|
74
74
|
|
|
75
75
|
// Validate if enabled
|
|
@@ -97,20 +97,20 @@ const loopDetectionStates = new WeakMap<Function, LoopDetectionState>();
|
|
|
97
97
|
// Deep equality check for objects
|
|
98
98
|
function deepEqual(obj1: any, obj2: any): boolean {
|
|
99
99
|
if (obj1 === obj2) return true;
|
|
100
|
-
|
|
100
|
+
|
|
101
101
|
if (!obj1 || !obj2) return false;
|
|
102
102
|
if (typeof obj1 !== 'object' || typeof obj2 !== 'object') return false;
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
const keys1 = Object.keys(obj1);
|
|
105
105
|
const keys2 = Object.keys(obj2);
|
|
106
|
-
|
|
106
|
+
|
|
107
107
|
if (keys1.length !== keys2.length) return false;
|
|
108
|
-
|
|
108
|
+
|
|
109
109
|
for (const key of keys1) {
|
|
110
110
|
if (!keys2.includes(key)) return false;
|
|
111
111
|
if (!deepEqual(obj1[key], obj2[key])) return false;
|
|
112
112
|
}
|
|
113
|
-
|
|
113
|
+
|
|
114
114
|
return true;
|
|
115
115
|
}
|
|
116
116
|
|
|
@@ -125,12 +125,12 @@ export function normalizeCallbacks(callbacks: any, debounceMs: number = 3000): C
|
|
|
125
125
|
const normalized: ComponentCallbacks = {
|
|
126
126
|
OpenEntityRecord: callbacks?.OpenEntityRecord || (() => {}),
|
|
127
127
|
RegisterMethod: callbacks?.RegisterMethod || (() => {}),
|
|
128
|
-
CreateSimpleNotification: callbacks?.CreateSimpleNotification || (() => {})
|
|
128
|
+
CreateSimpleNotification: callbacks?.CreateSimpleNotification || (() => {}),
|
|
129
129
|
};
|
|
130
130
|
|
|
131
131
|
// Copy any additional callbacks that might exist
|
|
132
132
|
if (callbacks) {
|
|
133
|
-
Object.keys(callbacks).forEach(key => {
|
|
133
|
+
Object.keys(callbacks).forEach((key) => {
|
|
134
134
|
if (typeof callbacks[key] === 'function' && !normalized.hasOwnProperty(key)) {
|
|
135
135
|
(normalized as any)[key] = callbacks[key];
|
|
136
136
|
}
|
|
@@ -198,7 +198,7 @@ export function mergeProps(...propsList: Partial<ComponentProps>[]): ComponentPr
|
|
|
198
198
|
utilities: {},
|
|
199
199
|
callbacks: {},
|
|
200
200
|
components: {},
|
|
201
|
-
styles: {} as ComponentStyles
|
|
201
|
+
styles: {} as ComponentStyles,
|
|
202
202
|
};
|
|
203
203
|
|
|
204
204
|
for (const props of propsList) {
|
|
@@ -229,22 +229,20 @@ export function mergeProps(...propsList: Partial<ComponentProps>[]): ComponentPr
|
|
|
229
229
|
|
|
230
230
|
return merged;
|
|
231
231
|
}
|
|
232
|
-
|
|
232
|
+
|
|
233
233
|
/**
|
|
234
234
|
* Creates a props transformer function
|
|
235
235
|
* @param transformations - Map of prop paths to transformer functions
|
|
236
236
|
* @returns Props transformer
|
|
237
237
|
*/
|
|
238
|
-
export function createPropsTransformer(
|
|
239
|
-
transformations: Record<string, (value: any) => any>
|
|
240
|
-
): (props: ComponentProps) => ComponentProps {
|
|
238
|
+
export function createPropsTransformer(transformations: Record<string, (value: any) => any>): (props: ComponentProps) => ComponentProps {
|
|
241
239
|
return (props: ComponentProps) => {
|
|
242
240
|
const transformed = { ...props };
|
|
243
241
|
|
|
244
242
|
for (const [path, transformer] of Object.entries(transformations)) {
|
|
245
243
|
const pathParts = path.split('.');
|
|
246
244
|
let current: any = transformed;
|
|
247
|
-
|
|
245
|
+
|
|
248
246
|
// Navigate to the parent of the target property
|
|
249
247
|
for (let i = 0; i < pathParts.length - 1; i++) {
|
|
250
248
|
if (!current[pathParts[i]]) {
|
|
@@ -270,19 +268,21 @@ export function createPropsTransformer(
|
|
|
270
268
|
* @param componentName - Component name for logging
|
|
271
269
|
* @returns Wrapped callbacks
|
|
272
270
|
*/
|
|
273
|
-
export function wrapCallbacksWithLogging(
|
|
274
|
-
callbacks: ComponentCallbacks,
|
|
275
|
-
componentName: string
|
|
276
|
-
): ComponentCallbacks {
|
|
271
|
+
export function wrapCallbacksWithLogging(callbacks: ComponentCallbacks, componentName: string): ComponentCallbacks {
|
|
277
272
|
const wrapped: ComponentCallbacks = {
|
|
278
273
|
OpenEntityRecord: callbacks?.OpenEntityRecord || (() => {}),
|
|
279
274
|
RegisterMethod: callbacks?.RegisterMethod || (() => {}),
|
|
280
|
-
CreateSimpleNotification: callbacks?.CreateSimpleNotification || (() => {})
|
|
275
|
+
CreateSimpleNotification: callbacks?.CreateSimpleNotification || (() => {}),
|
|
281
276
|
};
|
|
282
277
|
|
|
283
278
|
// Wrap any additional callbacks that might exist
|
|
284
|
-
Object.keys(callbacks).forEach(key => {
|
|
285
|
-
if (
|
|
279
|
+
Object.keys(callbacks).forEach((key) => {
|
|
280
|
+
if (
|
|
281
|
+
key !== 'OpenEntityRecord' &&
|
|
282
|
+
key !== 'RegisterMethod' &&
|
|
283
|
+
key !== 'CreateSimpleNotification' &&
|
|
284
|
+
typeof (callbacks as any)[key] === 'function'
|
|
285
|
+
) {
|
|
286
286
|
(wrapped as any)[key] = (...args: any[]) => {
|
|
287
287
|
if (!GetProductionStatus()) {
|
|
288
288
|
LogStatus(`[${componentName}] ${key} called with args:`, undefined, args);
|
|
@@ -311,7 +311,7 @@ export function wrapCallbacksWithLogging(
|
|
|
311
311
|
}
|
|
312
312
|
|
|
313
313
|
if (callbacks.CreateSimpleNotification) {
|
|
314
|
-
wrapped.CreateSimpleNotification = (message: string, style:
|
|
314
|
+
wrapped.CreateSimpleNotification = (message: string, style: 'none' | 'success' | 'error' | 'warning' | 'info', hideAfter?: number) => {
|
|
315
315
|
if (!GetProductionStatus()) {
|
|
316
316
|
LogStatus(`[${componentName}] CreateSimpleNotification called:`, undefined, { message, style, hideAfter });
|
|
317
317
|
}
|
|
@@ -329,14 +329,9 @@ export function wrapCallbacksWithLogging(
|
|
|
329
329
|
*/
|
|
330
330
|
export function extractPropPaths(componentCode: string): string[] {
|
|
331
331
|
const paths: string[] = [];
|
|
332
|
-
|
|
332
|
+
|
|
333
333
|
// Simple regex patterns to find prop access
|
|
334
|
-
const patterns = [
|
|
335
|
-
/props\.data\.(\w+)/g,
|
|
336
|
-
/props\.userState\.(\w+)/g,
|
|
337
|
-
/props\.utilities\.(\w+)/g,
|
|
338
|
-
/props\.callbacks\.(\w+)/g
|
|
339
|
-
];
|
|
334
|
+
const patterns = [/props\.data\.(\w+)/g, /props\.userState\.(\w+)/g, /props\.utilities\.(\w+)/g, /props\.callbacks\.(\w+)/g];
|
|
340
335
|
|
|
341
336
|
for (const pattern of patterns) {
|
|
342
337
|
let match;
|
|
@@ -346,4 +341,4 @@ export function extractPropPaths(componentCode: string): string[] {
|
|
|
346
341
|
}
|
|
347
342
|
|
|
348
343
|
return [...new Set(paths)]; // Remove duplicates
|
|
349
|
-
}
|
|
344
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @module @memberjunction/react-runtime/types
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { UserInfo } from '@memberjunction/
|
|
7
|
+
import { UserInfo } from '@memberjunction/global';
|
|
8
8
|
import { ComponentLibraryEntity } from '@memberjunction/core-entities';
|
|
9
9
|
import { ComponentLibraryDependency, ComponentStyles, ComponentObject } from '@memberjunction/interactive-component-types';
|
|
10
10
|
|
|
@@ -43,7 +43,7 @@ export interface CompileOptions {
|
|
|
43
43
|
|
|
44
44
|
/** Library dependencies that the component requires */
|
|
45
45
|
libraries?: ComponentLibraryDependency[];
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
/** Child component dependencies that the component requires */
|
|
48
48
|
dependencies?: Array<{ name: string; code?: string }>;
|
|
49
49
|
|
|
@@ -53,7 +53,6 @@ export interface CompileOptions {
|
|
|
53
53
|
allLibraries: ComponentLibraryEntity[];
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
57
56
|
/**
|
|
58
57
|
* Registry entry for a compiled component
|
|
59
58
|
*/
|
|
@@ -230,4 +229,4 @@ export * from './library-config';
|
|
|
230
229
|
export * from './dependency-types';
|
|
231
230
|
|
|
232
231
|
// Re-export ComponentObject for convenience
|
|
233
|
-
export { ComponentObject } from '@memberjunction/interactive-component-types';
|
|
232
|
+
export { ComponentObject } from '@memberjunction/interactive-component-types';
|