UNPKG

everything-dev

Version:

A consolidated product package for building Module Federation apps with oRPC APIs.

102 lines (100 loc) 3.94 kB
import { computeSriHash } from "./integrity.mjs"; import { createInstance, getInstance } from "@module-federation/enhanced/runtime"; import { setGlobalFederationInstance } from "@module-federation/runtime-core"; //#region src/mf.ts let mfInstance = null; function patchManifestFetchForSsrPublicPath(mf) { if (!mf || !mf.loaderHook?.lifecycle?.fetch?.on) return; if (mf.__everythingDevPatchedManifestFetch === true) return; mf.__everythingDevPatchedManifestFetch = true; mf.loaderHook.lifecycle.fetch.on((url, init) => { if (typeof url !== "string" || !url.endsWith("/mf-manifest.json")) return; return fetch(url, init).then((res) => res.json()).then((json) => { json.metaData = json.metaData ?? {}; json.metaData.ssrPublicPath = json.metaData.ssrPublicPath ?? url.replace(/\/mf-manifest\.json$/, "/"); return new Response(JSON.stringify(json), { headers: { "content-type": "application/json" } }); }); }); } function installIntegrityFetchHook(mf, registry) { if (!mf || !mf.loaderHook?.lifecycle?.fetch?.on) { console.warn("[SRI] MF lifecycle fetch hook not available, skipping integrity-in-pipeline"); return; } if (mf.__everythingDevIntegrityHook === true) return; mf.__everythingDevIntegrityHook = true; mf.loaderHook.lifecycle.fetch.on((url, init) => { if (typeof url !== "string") return; const expectedHash = registry.get(url); if (!expectedHash) return; return fetch(url, init).then(async (res) => { const buffer = Buffer.from(await res.arrayBuffer()); const computed = computeSriHash(buffer); if (computed !== expectedHash) { console.error(`[SRI] Integrity check failed in MF fetch pipeline for ${url}\n Expected: ${expectedHash}\n Computed: ${computed}`); return new Response(`Integrity check failed for ${url}`, { status: 500, statusText: "Integrity Check Failed" }); } console.log(`[SRI] Integrity verified in pipeline for ${url}`); return new Response(buffer, { status: res.status, statusText: res.statusText, headers: res.headers }); }); }); } function getFederationInstance() { if (mfInstance) return mfInstance; const existing = getInstance(); if (existing) { mfInstance = existing; setGlobalFederationInstance(mfInstance); patchManifestFetchForSsrPublicPath(mfInstance); return mfInstance; } mfInstance = createInstance({ name: "host", remotes: [] }); setGlobalFederationInstance(mfInstance); patchManifestFetchForSsrPublicPath(mfInstance); return mfInstance; } async function registerRemote(opts) { const instance = getFederationInstance(); const inferType = () => { if (opts.type) return opts.type; if (opts.entry.endsWith("/mf-manifest.json")) return "manifest"; if (opts.entry.endsWith("/remoteEntry.js")) return "script"; return typeof window === "undefined" ? "script" : "manifest"; }; const remoteType = inferType(); instance.registerRemotes([{ name: opts.name, entry: opts.entry, type: remoteType }]); } async function loadRemoteModule(specifier, options) { const instance = getFederationInstance(); if (typeof window === "undefined") await instance.initializeSharing?.("default"); const mod = await instance.loadRemote(specifier, options); if (!mod) throw new Error(`Failed to load remote module: ${specifier}`); return mod; } async function ensureNodeRuntimePlugin() { const instance = getFederationInstance(); if (typeof window !== "undefined") return; if (instance.__nodeRuntimePluginLoaded) return; const mod = await import("@module-federation/node/runtimePlugin"); const factory = mod?.default ?? mod; const plugin = typeof factory === "function" ? factory() : null; if (plugin) instance.registerPlugins([plugin]); instance.__nodeRuntimePluginLoaded = true; } //#endregion export { ensureNodeRuntimePlugin, getFederationInstance, installIntegrityFetchHook, loadRemoteModule, patchManifestFetchForSsrPublicPath, registerRemote }; //# sourceMappingURL=mf.mjs.map