UNPKG

@j2inn/app

Version:

J2 Innovations core application framework

127 lines (126 loc) 4.88 kB
/* * Copyright (c) 2021, J2 Innovations. All Rights Reserved */ /* eslint @typescript-eslint/no-explicit-any: "off" */ import { HNamespace } from 'haystack-core'; import { ResourceElement } from './ResourceElement'; /** * Loads the default exported module from some JS with the defined scope and module. * * @param scope The scope of the module to load. * @param module The name of the module to load. * @returns The loaded component. */ export function loadDefault(scope, module) { return async () => { // Initializes the share scope. This fills it with known provided modules // from this build and all remotes. await __webpack_init_sharing__('default'); const wnd = window; const container = wnd[scope]; // or get the container somewhere else. // Initialize the container, it may provide shared modules await container.init(__webpack_share_scopes__.default); const factory = await wnd[scope].get(module); return factory(); }; } function isCss(url) { return url.toLowerCase().endsWith('.css'); } /** * Asynchronously load the dynamic resource at runtime and wait for it to load. * * @param url The URL to load. * @returns A promise that's resolved once the resource has loaded. */ export async function loadDynamicResource(url, type = ScriptTagType.javascript) { globalThis.FIN_RESOURCE_PROMISE_CACHE ??= {}; let promise = globalThis.FIN_RESOURCE_PROMISE_CACHE[url]; if (!promise) { promise = globalThis.FIN_RESOURCE_PROMISE_CACHE[url] = new Promise((resolve, reject) => { let element; if (isCss(url)) { element = document.createElement('link'); element.href = url; element.rel = 'stylesheet'; } else { element = document.createElement('script'); element.src = url; element.type = type; element.async = true; } const resource = new ResourceElement(element); document.head.appendChild(element); const loadHandler = () => { resource.removeListeners(loadHandler, loadErrorHandler); resolve(resource); }; const loadErrorHandler = () => { resource.removeListeners(loadHandler, loadErrorHandler); reject(new Error('Resource loading failed')); }; resource.addListeners(loadHandler, loadErrorHandler); }); } return promise; } export async function loadDynamicResources(urls, type = ScriptTagType.javascript) { return Promise.all(urls.map((url) => loadDynamicResource(url, type))); } /** * Returns the pod name. * * @param def The def dict. * @returns The name of the pod the resource was loaded from. */ export function getPodName(def) { return HNamespace.getFeatureName(def.get('lib') ?? ''); } /** * Returns the remote entry point for an app. * * @param app The FIN app to get the remote entry point from. * @param ui The FIN app view to load the remote entry point from. * @param path The remote path to load. Defaults to `remoteEntry.js`. * @returns The remote entry point. */ export function getRemoteEntry(app, ui, path = 'remoteEntry.js') { const appName = HNamespace.getFeatureName(app.defName); // Find the POD file the resource needs to be loaded from. const podName = HNamespace.getFeatureName((ui ?? app).get('lib') ?? ''); // If the application is running in debug mode then attempt to // also load the remote entry from the other debug server if // specified. return typeof DEBUG === 'boolean' && DEBUG && typeof DEBUG_REMOTES === 'object' && DEBUG_REMOTES[podName] ? `${DEBUG_REMOTES[podName]}/${path}` : `/api/apps/${appName}/files/${podName}/dist/${path}`; } /** * Returns properties with values that can be rendered nicely as strings. * All objects and functions are excluded. All keys are made lowercase. * * @param props The properties to convert. * @returns The properties as strings. */ export function toStringProps(props) { return Object.keys(props).reduce((obj, key) => { const value = props[key]; const type = typeof value; if (type === 'string' || type === 'boolean' || type === 'number') { obj[key.toLowerCase()] = String(value); } return obj; }, {}); } export var ScriptTagType; (function (ScriptTagType) { ScriptTagType["module"] = "module"; ScriptTagType["importmap"] = "importmap"; ScriptTagType["javascript"] = "text/javascript"; ScriptTagType["json"] = "application/json"; })(ScriptTagType || (ScriptTagType = {}));