UNPKG

everything-dev

Version:

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

131 lines (129 loc) • 6.33 kB
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); const require_runtime = require('../../_virtual/_rolldown/runtime.cjs'); const require_services_resolution_resolver = require('../resolution/resolver.cjs'); const require_manifest_verify = require('./manifest-verify.cjs'); let node_fs = require("node:fs"); let node_path = require("node:path"); node_path = require_runtime.__toESM(node_path, 1); let every_plugin_build_artifact_names = require("every-plugin/build/artifact-names"); let every_plugin_version_manifest = require("every-plugin/version-manifest"); //#region src/services/deploy/version-manifest.ts /** Read a workspace dist's build-report.json (ticket 01's entry-name report). */ function readBuildReport(distRoot) { const reportPath = (0, node_path.join)(distRoot, "build-report.json"); if (!(0, node_fs.existsSync)(reportPath)) return null; try { return every_plugin_build_artifact_names.BuildEntryReportSchema.parse(JSON.parse((0, node_fs.readFileSync)(reportPath, "utf8"))); } catch { return null; } } /** * Compose the workspace's version manifest from the dist build reports and * the **server-computed** SRI map of the upload response (MAP decision 6 — * SRI is authoritative from the storage boundary, never computed * client-side). Returns null when the dist predates hashed entry names * (no report, or the SRI map lacks the entry) — the deploy leg then aborts: * uploaded workspaces must pin. */ function composeWorkspaceVersionManifest(input) { const { report, ssrReport, integrityMap, files, source, gitSha } = input; const entryIntegrity = integrityMap[report.entry]; if (!entryIntegrity) return null; const ssrEntry = ssrReport?.entry; const ssrIntegrity = ssrEntry ? integrityMap[`ssr/${ssrEntry}`] : void 0; return (0, every_plugin_version_manifest.composeVersionManifest)({ entry: report.entry, entryIntegrity, ...ssrEntry && ssrIntegrity ? { ssr: { entry: `ssr/${ssrEntry}`, integrity: ssrIntegrity } } : {}, ...report.browserManifest && integrityMap[report.browserManifest] ? { browserManifest: { file: report.browserManifest, integrity: integrityMap[report.browserManifest] } } : {}, ...report.css && integrityMap[report.css] ? { assets: { css: integrityMap[report.css] } } : {}, ...report.shared ?? ssrReport?.shared ? { shared: report.shared ?? ssrReport?.shared } : {}, ...files ? { files } : {}, ...source ? { source } : {}, ...gitSha ? { gitSha } : {} }); } const cache = /* @__PURE__ */ new Map(); function clearSlotVersionCache() { cache.clear(); } function slotVersionFromManifest(base, manifest) { const trimmedBase = base.replace(/\/$/, ""); return { entryUrl: `${trimmedBase}/${manifest.entry}`, entryIntegrity: manifest.entryIntegrity, ...manifest.browserManifest ? { browserManifestUrl: `${trimmedBase}/${manifest.browserManifest.file}` } : {}, ...manifest.ssr ? { ssrEntryUrl: `${trimmedBase}/${manifest.ssr.entry}`, ssrIntegrity: manifest.ssr.integrity } : {}, ...manifest.shared ? { sharedVersions: manifest.shared } : {}, ...manifest.files ? { files: manifest.files } : {}, ...manifest.source ? { source: manifest.source } : {} }; } /** * Staged-slot preference (ADR 0020/0021 self-contained tier): when a runtime * stages its own namespace under `BOS_BUNDLE_DIR`, a slot resolves from the * staged dist's own version manifest instead of the config's pin — pinned * manifest bytes that predate the image (deploy lag after a release bump) * cannot exist in the staged namespace, so their hashed files would 404 the * disk and fall through to the network, where the stale immutable bytes * still answer 200 and boot a foreign build. The staged manifest is trusted * (staged by the image build itself) and skipped entirely when the slot is * absent from the staged namespace or the pinned manifest is present (the * normal healthy case, which keeps the pin's SRI check). */ function readStagedSlotVersion(base, pin) { const bundleDir = process.env.BOS_BUNDLE_DIR; if (!bundleDir) return null; const slotDir = require_services_resolution_resolver.bundleUrlToStagedPath(base, bundleDir); if (!slotDir || !(0, node_fs.existsSync)(slotDir)) return null; const pinnedManifestPath = require_services_resolution_resolver.resolveContained(slotDir, pin.manifest); if (!pinnedManifestPath || (0, node_fs.existsSync)(pinnedManifestPath)) return null; const versionsDir = node_path.default.join(slotDir, "versions"); if (!(0, node_fs.existsSync)(versionsDir)) return null; const manifests = (0, node_fs.readdirSync)(versionsDir).filter((name) => name.endsWith(".json")).map((name) => node_path.default.join(versionsDir, name)).filter((file) => (0, node_fs.statSync)(file).isFile()).sort((a, b) => (0, node_fs.statSync)(b).mtimeMs - (0, node_fs.statSync)(a).mtimeMs || (a < b ? -1 : 1)); if (manifests.length === 0) return null; const manifestPath = manifests[0]; if (!manifestPath) return null; try { return slotVersionFromManifest(base, every_plugin_version_manifest.WorkspaceVersionManifestSchema.parse(JSON.parse((0, node_fs.readFileSync)(manifestPath, "utf8")))); } catch { return null; } } async function resolveSlotVersion(input) { const key = `${input.base}::${input.pin.manifest}::${input.pin.integrity}`; const cached = cache.get(key); if (cached) return cached; const staged = readStagedSlotVersion(input.base, input.pin); if (staged) { cache.set(key, staged); return staged; } const manifestUrl = require_manifest_verify.manifestDocumentUrl(input.base, input.pin.manifest); const verified = await require_manifest_verify.fetchVerifiedManifest({ base: input.base, pin: input.pin, fetchImpl: input.fetchImpl }); if (!verified.ok) throw new Error(`[SRI] version manifest verification failed for ${manifestUrl}: ${verified.reason}`); const manifest = every_plugin_version_manifest.WorkspaceVersionManifestSchema.parse(JSON.parse(verified.text)); const resolved = slotVersionFromManifest(input.base, manifest); cache.set(key, resolved); return resolved; } //#endregion exports.clearSlotVersionCache = clearSlotVersionCache; exports.composeWorkspaceVersionManifest = composeWorkspaceVersionManifest; exports.readBuildReport = readBuildReport; exports.resolveSlotVersion = resolveSlotVersion; //# sourceMappingURL=version-manifest.cjs.map