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.

214 lines 9.19 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LibraryLoader = void 0; const standard_libraries_1 = require("./standard-libraries"); const core_libraries_1 = require("./core-libraries"); const resource_manager_1 = require("./resource-manager"); const LIBRARY_LOADER_COMPONENT_ID = 'mj-react-runtime-library-loader-singleton'; class LibraryLoader { static async loadAllLibraries(config, additionalLibraries) { if (config) { standard_libraries_1.StandardLibraryManager.setConfiguration(config); } if (additionalLibraries && additionalLibraries.length > 0) { const currentConfig = standard_libraries_1.StandardLibraryManager.getConfiguration(); const mergedConfig = { libraries: [...currentConfig.libraries, ...additionalLibraries], metadata: { ...currentConfig.metadata, lastUpdated: new Date().toISOString() } }; standard_libraries_1.StandardLibraryManager.setConfiguration(mergedConfig); } return this.loadLibrariesFromConfig(); } static async loadLibrariesFromConfig(options) { const coreLibraries = (0, core_libraries_1.getCoreRuntimeLibraries)(); const corePromises = coreLibraries.map(lib => this.loadScript(lib.cdnUrl, lib.globalVariable)); const coreResults = await Promise.all(corePromises); const React = coreResults.find((_, i) => coreLibraries[i].globalVariable === 'React'); const ReactDOM = coreResults.find((_, i) => coreLibraries[i].globalVariable === 'ReactDOM'); const Babel = coreResults.find((_, i) => coreLibraries[i].globalVariable === 'Babel'); if (typeof window !== 'undefined') { if (React && !window.React) { window.React = React; console.log('✓ Exposed React as window.React for UMD compatibility'); } if (ReactDOM && !window.ReactDOM) { window.ReactDOM = ReactDOM; console.log('✓ Exposed ReactDOM as window.ReactDOM for UMD compatibility'); } if (!window.PropTypes) { window.PropTypes = {}; console.log('✓ Exposed empty PropTypes as window.PropTypes for UMD compatibility'); } } const config = standard_libraries_1.StandardLibraryManager.getConfiguration(); const enabledLibraries = standard_libraries_1.StandardLibraryManager.getEnabledLibraries(); let pluginLibraries = enabledLibraries.filter(lib => !(0, core_libraries_1.isCoreRuntimeLibrary)(lib.id)); if (options) { if (options.categories) { pluginLibraries = pluginLibraries.filter(lib => options.categories.includes(lib.category)); } if (options.excludeRuntimeOnly) { pluginLibraries = pluginLibraries.filter(lib => !lib.isRuntimeOnly); } } pluginLibraries.forEach(lib => { if (lib.cdnCssUrl) { this.loadCSS(lib.cdnCssUrl); } }); const pluginPromises = pluginLibraries.map(lib => this.loadScript(lib.cdnUrl, lib.globalVariable)); const pluginResults = await Promise.all(pluginPromises); const libraries = {}; pluginLibraries.forEach((lib, index) => { libraries[lib.globalVariable] = pluginResults[index]; }); return { React: React || window.React, ReactDOM: ReactDOM || window.ReactDOM, Babel: Babel || window.Babel, libraries }; } static async loadLibraries(options) { const { loadCore = true, loadUI = true, loadCSS = true, customLibraries = [] } = options; const categoriesToLoad = ['runtime']; if (loadCore) { categoriesToLoad.push('utility', 'charting'); } if (loadUI) { categoriesToLoad.push('ui'); } const result = await this.loadLibrariesFromConfig({ categories: categoriesToLoad }); if (customLibraries.length > 0) { const customPromises = customLibraries.map(({ url, globalName }) => this.loadScript(url, globalName)); const customResults = await Promise.all(customPromises); customLibraries.forEach(({ globalName }, index) => { result.libraries[globalName] = customResults[index]; }); } return result; } static async loadScript(url, globalName) { const existing = this.loadedResources.get(url); if (existing) { return existing.promise; } const promise = new Promise((resolve, reject) => { const existingGlobal = window[globalName]; if (existingGlobal) { resolve(existingGlobal); return; } const existingScript = document.querySelector(`script[src="${url}"]`); if (existingScript) { this.waitForScriptLoad(existingScript, globalName, resolve, reject); return; } const script = document.createElement('script'); script.src = url; script.async = true; script.crossOrigin = 'anonymous'; const cleanup = () => { script.removeEventListener('load', onLoad); script.removeEventListener('error', onError); }; const onLoad = () => { cleanup(); const global = window[globalName]; if (global) { resolve(global); } else { const timeoutId = resource_manager_1.resourceManager.setTimeout(LIBRARY_LOADER_COMPONENT_ID, () => { const delayedGlobal = window[globalName]; if (delayedGlobal) { resolve(delayedGlobal); } else { reject(new Error(`${globalName} not found after script load`)); } }, 100, { url, globalName }); } }; const onError = () => { cleanup(); reject(new Error(`Failed to load script: ${url}`)); }; script.addEventListener('load', onLoad); script.addEventListener('error', onError); document.head.appendChild(script); resource_manager_1.resourceManager.registerDOMElement(LIBRARY_LOADER_COMPONENT_ID, script); }); this.loadedResources.set(url, { element: document.querySelector(`script[src="${url}"]`), promise }); return promise; } static loadCSS(url) { if (this.loadedResources.has(url)) { return; } const existingLink = document.querySelector(`link[href="${url}"]`); if (existingLink) { return; } const link = document.createElement('link'); link.rel = 'stylesheet'; link.href = url; document.head.appendChild(link); resource_manager_1.resourceManager.registerDOMElement(LIBRARY_LOADER_COMPONENT_ID, link); this.loadedResources.set(url, { element: link, promise: Promise.resolve() }); } static waitForScriptLoad(script, globalName, resolve, reject) { const checkGlobal = () => { const global = window[globalName]; if (global) { resolve(global); } else { resource_manager_1.resourceManager.setTimeout(LIBRARY_LOADER_COMPONENT_ID, () => { const delayedGlobal = window[globalName]; if (delayedGlobal) { resolve(delayedGlobal); } else { reject(new Error(`${globalName} not found after script load`)); } }, 100, { context: 'waitForScriptLoad', globalName }); } }; if (script.complete || script.readyState === 'complete') { checkGlobal(); return; } const loadHandler = () => { checkGlobal(); }; resource_manager_1.resourceManager.addEventListener(LIBRARY_LOADER_COMPONENT_ID, script, 'load', loadHandler, { once: true }); } static getLoadedResources() { return this.loadedResources; } static clearCache() { this.loadedResources.forEach((resource, url) => { if (resource.element && resource.element.parentNode) { resource.element.parentNode.removeChild(resource.element); } }); this.loadedResources.clear(); resource_manager_1.resourceManager.cleanupComponent(LIBRARY_LOADER_COMPONENT_ID); } } exports.LibraryLoader = LibraryLoader; LibraryLoader.loadedResources = new Map(); //# sourceMappingURL=library-loader.js.map