UNPKG

@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.

203 lines 7.84 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.extractPropPaths = exports.wrapCallbacksWithLogging = exports.createPropsTransformer = exports.mergeProps = exports.validateComponentProps = exports.normalizeStyles = exports.normalizeCallbacks = exports.buildComponentProps = void 0; const core_1 = require("@memberjunction/core"); function buildComponentProps(data = {}, userState = {}, utilities = {}, callbacks = { OpenEntityRecord: () => { }, RegisterMethod: () => { }, CreateSimpleNotification: () => { } }, 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 = { OpenEntityRecord: callbacks?.OpenEntityRecord || (() => { }), RegisterMethod: callbacks?.RegisterMethod || (() => { }), CreateSimpleNotification: callbacks?.CreateSimpleNotification || (() => { }) }; if (callbacks) { Object.keys(callbacks).forEach(key => { if (typeof callbacks[key] === 'function' && !normalized.hasOwnProperty(key)) { normalized[key] = callbacks[key]; } }); } 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 = { OpenEntityRecord: callbacks?.OpenEntityRecord || (() => { }), RegisterMethod: callbacks?.RegisterMethod || (() => { }), CreateSimpleNotification: callbacks?.CreateSimpleNotification || (() => { }) }; Object.keys(callbacks).forEach(key => { if (key !== 'OpenEntityRecord' && key !== 'RegisterMethod' && key !== 'CreateSimpleNotification' && typeof callbacks[key] === 'function') { wrapped[key] = (...args) => { if (!(0, core_1.GetProductionStatus)()) { (0, core_1.LogStatus)(`[${componentName}] ${key} called with args:`, undefined, args); } return callbacks[key](...args); }; } }); if (callbacks.OpenEntityRecord) { wrapped.OpenEntityRecord = (entityName, key) => { if (!(0, core_1.GetProductionStatus)()) { (0, core_1.LogStatus)(`[${componentName}] OpenEntityRecord called:`, undefined, { entityName, key }); } callbacks.OpenEntityRecord(entityName, key); }; } if (callbacks.RegisterMethod) { wrapped.RegisterMethod = (methodName, handler) => { if (!(0, core_1.GetProductionStatus)()) { (0, core_1.LogStatus)(`[${componentName}] RegisterMethod called for:`, undefined, methodName); } callbacks.RegisterMethod(methodName, handler); }; } if (callbacks.CreateSimpleNotification) { wrapped.CreateSimpleNotification = (message, style, hideAfter) => { if (!(0, core_1.GetProductionStatus)()) { (0, core_1.LogStatus)(`[${componentName}] CreateSimpleNotification called:`, undefined, { message, style, hideAfter }); } callbacks.CreateSimpleNotification(message, style, hideAfter); }; } 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