vite-plugin-zephyr
Version:
Vite plugin for Zephyr
108 lines (107 loc) • 4.44 kB
JavaScript
const globalCacheKey = '__ZEPHYR_MANIFEST_CACHE__';
const _global = "u" > typeof window ? window : globalThis;
function getGlobalManifestCache() {
if (!_global[globalCacheKey]) _global[globalCacheKey] = new Map();
return _global[globalCacheKey];
}
const manifestFileName = 'zephyr-manifest.json';
function toHttpUrl(value) {
if (!value) return;
try {
const url = new URL(value);
return 'http:' === url.protocol || 'https:' === url.protocol ? url : void 0;
} catch {
return;
}
}
function getModuleUrl() {
try {
return import.meta.url;
} catch {
return;
}
}
function getDocumentBaseUrl() {
if ("u" < typeof document || 'function' != typeof document.querySelector) return;
if (!document.querySelector('base[href]')) return;
try {
return toHttpUrl(new URL('.', document.baseURI).href);
} catch {
return;
}
}
export function resolveManifestUrl(moduleUrl) {
const script = toHttpUrl(moduleUrl);
const documentBase = getDocumentBaseUrl();
if (documentBase && (!script || script.origin === documentBase.origin)) return `${documentBase.href}${manifestFileName}`;
if (script) return `${script.origin}/${manifestFileName}`;
return `/${manifestFileName}`;
}
function getRemotes(args) {
if (Array.isArray(args?.options?.remotes)) return args.options.remotes;
if (Array.isArray(args?.userOptions?.remotes)) return args.userOptions.remotes;
return [];
}
export default function createZephyrRuntimePlugin(options = {}) {
const defaultManifestUrl = resolveManifestUrl(getModuleUrl());
const { manifestUrl = defaultManifestUrl } = options;
let processedRemotes;
async function fetchManifest(url) {
try {
const response = await fetch(url);
if (!response.ok) return;
const manifest = await response.json().catch(()=>void 0);
if (!manifest) return void console.error('[Zephyr] Failed to parse manifest JSON');
return manifest;
} catch (error) {
console.error('[Zephyr] Unexpected error fetching manifest:', error);
return;
}
}
const manifestCache = getGlobalManifestCache();
if (!manifestCache.has(manifestUrl)) manifestCache.set(manifestUrl, fetchManifest(manifestUrl));
const zephyrManifestPromise = manifestCache.get(manifestUrl);
return {
name: 'zephyr-runtime-remote-resolver',
async beforeRequest (args) {
const zephyrManifest = await zephyrManifestPromise;
if (!processedRemotes) processedRemotes = identifyRemotes(args, zephyrManifest);
const remoteName = 'string' == typeof args?.id ? args.id.split('/')[0] : void 0;
if (!remoteName || !processedRemotes[remoteName]) return args;
const resolvedUrl = getResolvedRemoteUrl(processedRemotes[remoteName]);
const remotes = getRemotes(args);
const targetRemote = remotes.find((remote)=>hasEntry(remote) && (remote.name === remoteName || remote.alias === remoteName));
if (!targetRemote) return args;
targetRemote.entry = resolvedUrl;
return args;
}
};
}
function identifyRemotes(args, zephyrManifest) {
const identifiedRemotes = {};
if (!zephyrManifest) return identifiedRemotes;
const remotes = getRemotes(args);
if (!remotes.length) return identifiedRemotes;
const dependencies = zephyrManifest.dependencies ?? {};
remotes.forEach((remote)=>{
const resolvedRemote = dependencies[remote.name] ?? dependencies[remote.alias ?? ''];
if (resolvedRemote) {
identifiedRemotes[remote.name] = resolvedRemote;
if (remote.alias && remote.alias !== remote.name) identifiedRemotes[remote.alias] = resolvedRemote;
}
});
return identifiedRemotes;
}
function hasEntry(remote) {
return null != remote && 'object' == typeof remote && 'entry' in remote && 'string' == typeof remote.entry;
}
function getResolvedRemoteUrl(resolvedRemote) {
const _window = "u" > typeof window ? window : globalThis;
const sessionEdgeURL = _window.sessionStorage?.getItem?.(resolvedRemote.application_uid);
let edgeUrl = sessionEdgeURL ?? resolvedRemote.remote_entry_url;
if (-1 !== edgeUrl.indexOf('@')) {
const [, url] = edgeUrl.split('@');
edgeUrl = url;
}
return edgeUrl;
}