UNPKG

everything-dev

Version:

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

109 lines (107 loc) • 3.67 kB
import { collectSlotPinRefs } from "./rollback.mjs"; import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; import { createHash } from "node:crypto"; //#region src/deploy-diff.ts const BUNDLE_BASE_PATTERN = /\/bundles\/([^/]+)\/([^/]+)\/([^/]+)\/$/; function workspaceKeyOfBase(base) { const match = BUNDLE_BASE_PATTERN.exec(`${base.replace(/\/$/, "")}/`); return match ? match[3] : null; } /** The sha384 SRI the storage route would compute for these bytes. */ function localObjectIntegrity(bytes) { return `sha384-${createHash("sha384").update(bytes).digest("base64")}`; } function localSriMap(files) { return Object.fromEntries(files.map((file) => [file.path, localObjectIntegrity(file.bytes)])); } const deployStatePath = (configDir) => join(configDir, ".bos", "deploy-state.json"); function readDeployState(configDir) { const path = deployStatePath(configDir); if (!existsSync(path)) return { version: 1, apps: {} }; try { const parsed = JSON.parse(readFileSync(path, "utf8")); if (parsed.version !== 1 || typeof parsed.apps !== "object" || parsed.apps === null) return { version: 1, apps: {} }; return { version: 1, apps: parsed.apps }; } catch { return { version: 1, apps: {} }; } } function writeDeployState(configDir, state) { const path = deployStatePath(configDir); mkdirSync(dirname(path), { recursive: true }); writeFileSync(path, `${JSON.stringify(state, null, 2)}\n`); } function upsertDeployStatePins(configDir, account, gateway, pins) { const state = readDeployState(configDir); const appKey = `${account}/${gateway}`; state.apps[appKey] = { ...state.apps[appKey], ...pins }; writeDeployState(configDir, state); } /** Previous pins by workspace key, from the local deploy-state pointer. */ function pinsFromDeployState(configDir, account, gateway) { return readDeployState(configDir).apps[`${account}/${gateway}`] ?? {}; } /** Previous pins by workspace key, from the published config's slot pins. */ function pinsFromPublishedConfig(config, account, gateway) { const pins = {}; for (const ref of collectSlotPinRefs(config)) { const workspace = workspaceKeyOfBase(ref.base); const nsMatch = BUNDLE_BASE_PATTERN.exec(`${ref.base.replace(/\/$/, "")}/`); if (!workspace || !nsMatch || nsMatch[1] !== account || nsMatch[2] !== gateway) continue; pins[workspace] = ref.pin; } return pins; } function diffWorkspaceFiles(files, localSri, prevFiles) { const upload = []; let skipped = 0; for (const file of files) { if (prevFiles[file.path] !== void 0 && prevFiles[file.path] === localSri[file.path]) { skipped += 1; continue; } upload.push(file); } return { upload, skipped }; } /** * The manifest's merged per-file map for this deploy: uploaded files carry the * server-computed SRI from the upload response; skipped files carry the * previous manifest's server-computed SRI (byte-identical to the local hash by * the skip decision). Files that left the dist carry nothing. */ function mergedFileIntegrity(files, uploadedIntegrity, prevFiles) { const merged = {}; for (const file of files) { const uploaded = uploadedIntegrity[file.path]; if (uploaded) { merged[file.path] = uploaded; continue; } const carried = prevFiles?.[file.path]; if (carried) merged[file.path] = carried; } return merged; } //#endregion export { BUNDLE_BASE_PATTERN, diffWorkspaceFiles, localObjectIntegrity, localSriMap, mergedFileIntegrity, pinsFromDeployState, pinsFromPublishedConfig, readDeployState, upsertDeployStatePins, workspaceKeyOfBase, writeDeployState }; //# sourceMappingURL=deploy-diff.mjs.map