@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.
167 lines • 6.13 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractPropPaths = exports.wrapCallbacksWithLogging = exports.createPropsTransformer = exports.mergeProps = exports.validateComponentProps = exports.normalizeStyles = exports.normalizeCallbacks = exports.buildComponentProps = void 0;
function buildComponentProps(data = {}, userState = {}, utilities = {}, callbacks = {}, components = {}, styles, options = {}, onStateChanged) {
const { validate = true, transformData, transformState, debounceUpdateUserState = 3000 } = options;
const transformedData = transformData ? transformData(data) : data;
const transformedState = transformState ? transformState(userState) : userState;
const props = {
data: transformedData,
userState: transformedState,
utilities,
callbacks: normalizeCallbacks(callbacks, debounceUpdateUserState),
components,
styles: normalizeStyles(styles),
onStateChanged
};
if (validate) {
validateComponentProps(props);
}
return props;
}
exports.buildComponentProps = buildComponentProps;
const updateUserStateSubjects = new WeakMap();
const updateUserStateSubscriptions = new WeakMap();
const loopDetectionStates = new WeakMap();
function deepEqual(obj1, obj2) {
if (obj1 === obj2)
return true;
if (!obj1 || !obj2)
return false;
if (typeof obj1 !== 'object' || typeof obj2 !== 'object')
return false;
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length)
return false;
for (const key of keys1) {
if (!keys2.includes(key))
return false;
if (!deepEqual(obj1[key], obj2[key]))
return false;
}
return true;
}
function normalizeCallbacks(callbacks, debounceMs = 3000) {
const normalized = {};
if (callbacks.RefreshData && typeof callbacks.RefreshData === 'function') {
normalized.RefreshData = callbacks.RefreshData;
}
if (callbacks.OpenEntityRecord && typeof callbacks.OpenEntityRecord === 'function') {
normalized.OpenEntityRecord = callbacks.OpenEntityRecord;
}
return normalized;
}
exports.normalizeCallbacks = normalizeCallbacks;
function normalizeStyles(styles) {
return styles;
}
exports.normalizeStyles = normalizeStyles;
function validateComponentProps(props) {
if (props.data === null || props.data === undefined) {
throw new Error('Component props.data cannot be null or undefined');
}
if (props.userState === null) {
throw new Error('Component props.userState cannot be null');
}
if (props.utilities === null) {
throw new Error('Component props.utilities cannot be null');
}
if (!props.callbacks || typeof props.callbacks !== 'object') {
throw new Error('Component props.callbacks must be an object');
}
for (const [key, value] of Object.entries(props.callbacks)) {
if (value !== undefined && typeof value !== 'function') {
throw new Error(`Component callback "${key}" must be a function`);
}
}
}
exports.validateComponentProps = validateComponentProps;
function mergeProps(...propsList) {
const merged = {
data: {},
userState: {},
utilities: {},
callbacks: {},
components: {},
styles: {}
};
for (const props of propsList) {
if (props.data) {
merged.data = { ...merged.data, ...props.data };
}
if (props.userState) {
merged.userState = { ...merged.userState, ...props.userState };
}
if (props.utilities) {
merged.utilities = { ...merged.utilities, ...props.utilities };
}
if (props.callbacks) {
merged.callbacks = { ...merged.callbacks, ...props.callbacks };
}
if (props.components) {
merged.components = { ...merged.components, ...props.components };
}
if (props.styles) {
merged.styles = { ...merged.styles, ...props.styles };
}
}
return merged;
}
exports.mergeProps = mergeProps;
function createPropsTransformer(transformations) {
return (props) => {
const transformed = { ...props };
for (const [path, transformer] of Object.entries(transformations)) {
const pathParts = path.split('.');
let current = transformed;
for (let i = 0; i < pathParts.length - 1; i++) {
if (!current[pathParts[i]]) {
current[pathParts[i]] = {};
}
current = current[pathParts[i]];
}
const lastPart = pathParts[pathParts.length - 1];
if (current[lastPart] !== undefined) {
current[lastPart] = transformer(current[lastPart]);
}
}
return transformed;
};
}
exports.createPropsTransformer = createPropsTransformer;
function wrapCallbacksWithLogging(callbacks, componentName) {
const wrapped = {};
if (callbacks.RefreshData) {
wrapped.RefreshData = () => {
console.log(`[${componentName}] RefreshData called`);
callbacks.RefreshData();
};
}
if (callbacks.OpenEntityRecord) {
wrapped.OpenEntityRecord = (entityName, key) => {
console.log(`[${componentName}] OpenEntityRecord called:`, { entityName, key });
callbacks.OpenEntityRecord(entityName, key);
};
}
return wrapped;
}
exports.wrapCallbacksWithLogging = wrapCallbacksWithLogging;
function extractPropPaths(componentCode) {
const paths = [];
const patterns = [
/props\.data\.(\w+)/g,
/props\.userState\.(\w+)/g,
/props\.utilities\.(\w+)/g,
/props\.callbacks\.(\w+)/g
];
for (const pattern of patterns) {
let match;
while ((match = pattern.exec(componentCode)) !== null) {
paths.push(match[0]);
}
}
return [...new Set(paths)];
}
exports.extractPropPaths = extractPropPaths;
//# sourceMappingURL=prop-builder.js.map