1(function (global) { 2 const MODULES_ROOT_MARKER = '/editor/apps/modules'; 3 const modules = {}; 4 window.loadedExternals = window.loadedExternals || {}; 5 let basePromise = null; 6 let manifestFile = null; 7 8 // Environment, resolved once commonProps exists (see resolveEnvironment, 9 // run after waitForCommonProps in init). There is exactly one module 10 // source. Local dev: server.for.resources is the local static server 11 // (localhost:8888), which 302-redirects module and /@vite/client requests 12 // to the group Vite dev server â Vite serves source and injects its own 13 // styles, so there is no manifest. Prod: server.for.resources is blank, so 14 // modules load from common.resources.folder (CDN) and their eager CSS 15 // comes from the build manifest. 16 let isDev = false; 17 let serverName = ''; 18 let modulesRoot = ''; 19 20 // commonProps is injected by a JSP <script> before this one, but on some 21 // pages/timings it isn't defined yet when this script evaluates. Poll for 22 // it so init never reads an undefined global; resolve (don't hang) after a 23 // cap so a genuinely missing commonProps surfaces as a normal error below. 24 function waitForCommonProps() { 25 return new Promise(function (resolve) { 26 if (typeof commonProps !== 'undefined' && commonProps) { 27 resolve(); 28 return; 29 } 30 const startedAt = Date.now(); 31 const intervalId = setInterval(function () { 32 if ( 33 (typeof commonProps !== 'undefined' && commonProps) || 34 Date.now() - startedAt > 30000 35 ) { 36 clearInterval(intervalId); 37 resolve(); 38 } 39 }, 20); 40 }); 41 } 42 43 function resolveEnvironment() { 44 const serverForResources = commonProps['server.for.resources']; 45 isDev = (serverForResources || '').includes('localhost'); 46 serverName = 47 serverForResources || commonProps['common.resources.folder']; 48 modulesRoot = serverName + MODULES_ROOT_MARKER; 49 } 50 51 function loadExternals() { 52 const url = commonProps['externalsUrl']; 53 if (window.loadedExternals[url]) { 54 return Promise.resolve(window.loadedExternals[url]); 55 } 56 return new Promise(function (resolve) { 57 $.ajax({ 58 url: url, 59 type: 'GET', 60 dataType: 'script', 61 cache: true, 62 success: function (result) { 63 window.loadedExternals[url] = result || true; 64 resolve(result); 65 }, 66 error: function (xhr, status, error) { 67 console.error( 68 'loading script ' + url + ' failed.', 69 error 70 ); 71 resolve(); 72 }, 73 }); 74 }); 75 } 76 77 // The consolidated Vite build ships a single manifest at the modules root. 78 // Resolves to the manifest object, or null when there is none (dev, or a 79 // build that still inlines its CSS). Best-effort: never rejects. 80 function fetchManifest() { 81 if(isDev){ 82 return Promise.resolve() 83 }
84 return fetch(modulesRoot + '/.vite/manifest-apps.json') 85 .then(function (response) { 86 return response.ok ? response.json() : null; 87 }) 88 .then(function (manifest) { 89 manifestFile = manifest; 90 }) 91 .catch(function () { 92 return null; 93 }); 94 } 95 96 // Vite's HMR client. The static dev server redirects /@vite/client to the 97 // apps Vite dev server (it knows the dynamic port we don't). Loading it 98 // sets up the HMR socket + style hot-swap runtime the dev-transformed 99 // modules expect; deduped with the copy modules import themselves. 100 function loadViteClient() { 101 if(isDev) { 102 return import(serverName + '/@vite/client').catch(function (err) { 103 console.error('Unable to load @vite/client', err); 104 }); 105 } 106 return Promise.resolve() 107 } 108 109 function buildModuleUrl(moduleName) { 110 return modulesRoot + '/' + moduleName + '/' + moduleName + '.js'; 111 } 112 113 // Modules emit real `.css` files (Vite `cssCodeSplit: true`) instead of 114 // inlining styles into the JS bundle, so `url(...)` assets resolve relative 115 // to the stylesheet. Since we render no HTML, the entry stylesheet has no 116 // <link> â inject the links from the build manifest before the JS import 117 // starts, matching the links-before-script markup of Vite's 118 // backend-integration guide (https://vite.dev/guide/backend-integration). 119 function injectModuleCss(manifest, moduleName) { 120 // Pick this module's entry record by its emitted JS. The group 121 // manifest holds one entry per module, with files relative to the 122 // modules root (`<module>/<module>.js`). 123 const jsFilePath = moduleName + '/' + moduleName + '.js'; 124 const entryKey = Object.keys(manifest).find(function (key) { 125 return manifest[key].isEntry && manifest[key].file === jsFilePath; 126 }); 127 if (!entryKey) { 128 return; 129 } 130 // CSS owned by dynamic imports is loaded on demand by Vite's preload 131 // helper, so only the entry and its static `imports` are walked here. 132 const cssFiles = []; 133 const pushCss = function (record) { 134 (record.css || []).forEach(function (cssPath) { 135 if (cssFiles.indexOf(cssPath) === -1) { 136 cssFiles.push(cssPath); 137 } 138 }); 139 }; 140 pushCss(manifest[entryKey]); 141 // Mirrors `importedChunks()` from the Vite guide: each chunk's 142 // static imports are emitted before the chunk itself. 143 const seen = {}; 144 (function collectImported(key) { 145 (manifest[key].imports || []).forEach(function (imported) { 146 if (seen[imported] || !manifest[imported]) { 147 return; 148 } 149 seen[imported] = true; 150 collectImported(imported); 151 pushCss(manifest[imported]); 152 }); 153 })(entryKey); 154 cssFiles.forEach(function (cssPath) { 155 insertStylesheet(modulesRoot + '/' + cssPath, moduleName); 156 }); 157 } 158 159 function insertStylesheet(href, moduleName) { 160 if ( 161 document.querySelector( 162 'link[rel="stylesheet"][href="' + href + '"]' 163 ) 164 ) { 165 return; 166 } 167 const link = document.createElement('link'); 168 link.rel = 'stylesheet'; 169 link.href = href; 170 link.setAttribute('data-module', moduleName); 171 document.head.appendChild(link); 172 } 173 174 // A failed dynamic import() throws a bare "Failed to fetch dynamically 175 // imported module" TypeError with no HTTP detail â status, content-type 176 // and body are all hidden. Re-request the same URL with fetch() so the 177 // real server response is visible: a 404/500, an HTML error page served 178 // with a JS content-type, a CORS rejection, or a genuine network failure 179 // each surface differently here. Best-effort: never throws. 180 async function probeModuleUrl(url) { 181 if (!url) { 182 return { probeError: 'url not resolved' }; 183 } 184 try { 185 const response = await fetch(url, { cache: 'no-store' }); 186 let bodySnippet = ''; 187 try { 188 bodySnippet = (await response.text()).slice(0, 200); 189 } catch (bodyErr) { 190 bodySnippet = '<unreadable body: ' + bodyErr + '>'; 191 } 192 return { 193 status: response.status, 194 statusText: response.statusText, 195 ok: response.ok, 196 type: response.type, 197 redirected: response.redirected, 198 finalUrl: response.url, 199 contentType: response.headers.get('content-type'), 200 bodySnippet: bodySnippet, 201 }; 202 } catch (probeErr) { 203 // fetch itself rejected â same failure class as the import 204 // (network down, DNS, CORS). The message distinguishes them. 205 return { probeError: String(probeErr) }; 206 } 207 } 208 209 const RETRY_DELAY_MS = 300; 210 const MAX_RETRIES = 3; 211 212 // Chrome, Firefox and Safari each word the same fetch failure differently. 213 const FETCH_IMPORT_ERRORS = [ 214 'Failed to fetch dynamically imported module', 215 'error loading dynamically imported module', 216 'Importing a module script failed', 217 ]; 218 219 function isFetchImportError(err) { 220 const message = (err && err.message) || ''; 221 return FETCH_IMPORT_ERRORS.some(function (wording) { 222 return message.indexOf(wording) !== -1; 223 }); 224 } 225 226 function delay(ms) { 227 return new Promise(function (resolve) { 228 setTimeout(resolve, ms); 229 }); 230 } 231 232 async function importModule(moduleUrl) { 233 for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) { 234 try { 235 return await import( 236 attempt === 0 ? moduleUrl : moduleUrl + '?retry=' + attempt 237 ); 238 } catch (err) { 239 if (!isFetchImportError(err) || attempt === MAX_RETRIES) { 240 throw err; 241 } 242 await delay(RETRY_DELAY_MS); 243 } 244 } 245 } 246 247 async function getModuleAsync(moduleName) { 248 if (modules[moduleName]) { 249 return modules[moduleName]; 250 } 251 let moduleUrl = null; 252 try { 253 await basePromise; 254 if (!isDev && manifestFile) { 255 injectModuleCss(manifestFile, moduleName); 256 } 257 moduleUrl = buildModuleUrl(moduleName); 258 const module = await importModule(moduleUrl); 259 modules[moduleName] = module; 260 return module; 261 } catch (err) { 262 const probe = await probeModuleUrl(moduleUrl); 263 console.error('Error in loading ' + moduleName + " | " + JSON.stringify({ 264 moduleName: moduleName, 265 url: moduleUrl, 266 isDev: isDev, 267 serverName: serverName, 268 online: 269 typeof navigator !== 'undefined' ? navigator.onLine : null, 270 errorName: err && err.name, 271 errorMessage: err && err.message, 272 probe: probe, 273 }), err); 274 throw new Error('Failed to load module ' + moduleName, { 275 cause: err, 276 }); 277 } 278 } 279 280 function getModuleSync(moduleName) { 281 return modules[moduleName]; 282 } 283 284 function setModule(moduleName, module) { 285 modules[moduleName] = module; 286 } 287
288 (function init() { 289 const loadedModules = window.loadedModules; 290 if (loadedModules) { 291 Object.keys(loadedModules).forEach(function (name) { 292 modules[name] = loadedModules[name]; 293 }); 294 } 295 296 basePromise = waitForCommonProps().then(function () { 297 resolveEnvironment(); 298 return Promise.all([ 299 loadExternals(), 300 loadViteClient(), 301 fetchManifest(), 302 ]); 303 }); 304 })(); 305 306 global.$.modulesManager = { 307 getModuleAsync: getModuleAsync, 308 getModuleSync: getModuleSync, 309 setModule: setModule, 310 }; 311})(window);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.