@memberjunction/react-runtime
Version:
Platform-agnostic React component runtime for MemberJunction. Provides core compilation, registry, and execution capabilities for React components in any JavaScript environment.
176 lines • 7.38 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.countComponentsInHierarchy = exports.flattenComponentHierarchy = exports.validateComponentSpec = exports.registerComponentHierarchy = exports.ComponentHierarchyRegistrar = void 0;
class ComponentHierarchyRegistrar {
constructor(compiler, registry, runtimeContext) {
this.compiler = compiler;
this.registry = registry;
this.runtimeContext = runtimeContext;
}
async registerHierarchy(rootSpec, options) {
const { styles, namespace = 'Global', version = 'v1', continueOnError = true, allowOverride = true } = options;
console.log('🌳 ComponentHierarchyRegistrar.registerHierarchy:', {
rootComponent: rootSpec.name,
hasLibraries: !!(rootSpec.libraries && rootSpec.libraries.length > 0),
libraryCount: rootSpec.libraries?.length || 0,
libraries: rootSpec.libraries?.map(l => l.name)
});
const registeredComponents = [];
const errors = [];
const warnings = [];
const rootResult = await this.registerSingleComponent(rootSpec, { styles, namespace, version, allowOverride, allLibraries: options.allLibraries });
if (rootResult.success) {
registeredComponents.push(rootSpec.name);
}
else {
errors.push(rootResult.error);
if (!continueOnError) {
return { success: false, registeredComponents, errors, warnings };
}
}
const childComponents = rootSpec.dependencies || [];
if (childComponents.length > 0) {
const childResult = await this.registerChildComponents(childComponents, { styles, namespace, version, continueOnError, allowOverride, allLibraries: options.allLibraries }, registeredComponents, errors, warnings);
}
return {
success: errors.length === 0,
registeredComponents,
errors,
warnings
};
}
async registerSingleComponent(spec, options) {
const { styles, namespace = 'Global', version = 'v1', allowOverride = true } = options;
try {
if (!spec.code) {
return {
success: true,
error: undefined
};
}
const existingComponent = this.registry.get(spec.name, namespace, version);
if (existingComponent && !allowOverride) {
return {
success: false,
error: {
componentName: spec.name,
error: `Component already registered in ${namespace}/${version}`,
phase: 'registration'
}
};
}
const compileOptions = {
componentName: spec.name,
componentCode: spec.code,
styles,
libraries: spec.libraries,
allLibraries: options.allLibraries
};
console.log(`🔧 Compiling component ${spec.name} with libraries:`, {
libraryCount: spec.libraries?.length || 0,
libraries: spec.libraries?.map(l => ({ name: l.name, globalVariable: l.globalVariable }))
});
const compilationResult = await this.compiler.compile(compileOptions);
if (!compilationResult.success) {
return {
success: false,
error: {
componentName: spec.name,
error: compilationResult.error?.message || 'Unknown compilation error',
phase: 'compilation'
}
};
}
const componentFactory = compilationResult.component.component(this.runtimeContext, styles);
this.registry.register(spec.name, componentFactory.component, namespace, version);
return { success: true };
}
catch (error) {
return {
success: false,
error: {
componentName: spec.name,
error: error instanceof Error ? error.message : String(error),
phase: 'registration'
}
};
}
}
async registerChildComponents(children, options, registeredComponents, errors, warnings) {
for (const child of children) {
const childResult = await this.registerSingleComponent(child, {
styles: options.styles,
namespace: options.namespace,
version: options.version,
allowOverride: options.allowOverride,
allLibraries: options.allLibraries
});
if (childResult.success) {
if (child.code) {
registeredComponents.push(child.name);
}
}
else {
errors.push(childResult.error);
if (!options.continueOnError) {
return;
}
}
const nestedChildren = child.dependencies || [];
if (nestedChildren.length > 0) {
await this.registerChildComponents(nestedChildren, options, registeredComponents, errors, warnings);
}
}
}
}
exports.ComponentHierarchyRegistrar = ComponentHierarchyRegistrar;
async function registerComponentHierarchy(rootSpec, compiler, registry, runtimeContext, options) {
const registrar = new ComponentHierarchyRegistrar(compiler, registry, runtimeContext);
return registrar.registerHierarchy(rootSpec, options);
}
exports.registerComponentHierarchy = registerComponentHierarchy;
function validateComponentSpec(spec) {
const errors = [];
if (!spec.name) {
errors.push('Component specification must have a name');
}
if (spec.code) {
if (typeof spec.code !== 'string') {
errors.push(`Component code for ${spec.name} must be a string`);
}
if (spec.code.trim().length === 0) {
errors.push(`Component code for ${spec.name} cannot be empty`);
}
}
const children = spec.dependencies || [];
children.forEach((child, index) => {
const childErrors = validateComponentSpec(child);
childErrors.forEach(error => {
errors.push(`Child ${index} (${child.name || 'unnamed'}): ${error}`);
});
});
return errors;
}
exports.validateComponentSpec = validateComponentSpec;
function flattenComponentHierarchy(rootSpec) {
const components = [rootSpec];
const children = rootSpec.dependencies || [];
children.forEach(child => {
components.push(...flattenComponentHierarchy(child));
});
return components;
}
exports.flattenComponentHierarchy = flattenComponentHierarchy;
function countComponentsInHierarchy(rootSpec, includeEmpty = false) {
let count = 0;
if (includeEmpty || rootSpec.code) {
count = 1;
}
const children = rootSpec.dependencies || [];
children.forEach(child => {
count += countComponentsInHierarchy(child, includeEmpty);
});
return count;
}
exports.countComponentsInHierarchy = countComponentsInHierarchy;
//# sourceMappingURL=component-hierarchy.js.map