UNPKG

everything-dev

Version:

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

154 lines (152 loc) 5.41 kB
import { rebuildOrderedConfig } from "./merge.mjs"; import { BosConfigSchema } from "./types.mjs"; import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; import { createHash } from "node:crypto"; //#region src/shared.ts function sha256(input) { return createHash("sha256").update(input).digest("hex"); } function extractSemverExact(input) { if (typeof input !== "string") return null; const match = input.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/); return match ? match[0] : null; } function caretRange(version) { return `^${version}`; } function stableDepsObject(deps) { const keys = Object.keys(deps).sort((a, b) => a.localeCompare(b)); const out = {}; for (const k of keys) out[k] = deps[k]; return out; } function writeFileIfChanged(filePath, nextContent) { try { if (readFileSync(filePath, "utf-8") === nextContent) return false; } catch {} writeFileSync(filePath, nextContent); return true; } function fingerprintResolved(deps) { const stable = stableDepsObject(deps); return sha256(JSON.stringify(stable)); } function getSharedUiDeps(bosConfig) { return (bosConfig.shared ?? {}).ui ?? {}; } async function syncAndGenerateSharedUi(opts) { const bosConfigPath = join(opts.configDir, "bos.config.json"); const resolvedConfigPath = join(opts.configDir, ".bos", "bos.resolved-config.json"); const packageJsonPath = join(opts.configDir, "package.json"); const generatedPath = join(opts.configDir, ".bos", "generated", "shared-ui.json"); let bosConfig; if (opts.bosConfig) bosConfig = opts.bosConfig; else { const raw = JSON.parse(readFileSync(bosConfigPath, "utf-8")); bosConfig = BosConfigSchema.parse(raw); } let pkgJson = {}; try { pkgJson = JSON.parse(readFileSync(packageJsonPath, "utf-8")); } catch {} const originalBos = JSON.stringify(bosConfig); const originalPkg = JSON.stringify(pkgJson); const catalog = pkgJson?.workspaces?.catalog ?? {}; const sharedUi = getSharedUiDeps(bosConfig); const mode = opts.hostMode === "local" ? "catalog->bos" : "bos->catalog"; if (mode === "catalog->bos") for (const [name, cfg] of Object.entries(sharedUi)) { const dep = cfg; const version = catalog[name] ?? extractSemverExact(dep.version) ?? extractSemverExact(dep.requiredVersion); if (!version) continue; dep.version = version; dep.requiredVersion = caretRange(version); dep.shareScope = dep.shareScope ?? "default"; } else { for (const [name, cfg] of Object.entries(sharedUi)) { const dep = cfg; const version = extractSemverExact(dep.version) ?? extractSemverExact(dep.requiredVersion); if (!version) continue; dep.version = version; dep.requiredVersion = caretRange(version); dep.shareScope = dep.shareScope ?? "default"; if (catalog[name] !== version) catalog[name] = version; } if (!pkgJson.workspaces) pkgJson.workspaces = { packages: [], catalog: {} }; pkgJson.workspaces.catalog = catalog; } const nextBos = JSON.stringify(bosConfig); const nextPkg = JSON.stringify(pkgJson); const bosConfigChanged = nextBos !== originalBos; const catalogChanged = nextPkg !== originalPkg; if (bosConfigChanged) if (mode === "catalog->bos") { const resolvedDir = dirname(resolvedConfigPath); if (!existsSync(resolvedDir)) mkdirSync(resolvedDir, { recursive: true }); const ordered = rebuildOrderedConfig(bosConfig); const resolvedOutput = { _resolved: { env: opts.env ?? "development", resolvedAt: (/* @__PURE__ */ new Date()).toISOString(), extendsChain: opts.extendsChain ?? [], source: "shared-sync" }, ...ordered }; writeFileIfChanged(resolvedConfigPath, `${JSON.stringify(resolvedOutput, null, 2)}\n`); } else writeFileIfChanged(bosConfigPath, `${JSON.stringify(bosConfig, null, 2)}\n`); if (catalogChanged) writeFileIfChanged(packageJsonPath, `${JSON.stringify(pkgJson, null, 2)}\n`); const resolvedDeps = {}; for (const [name, cfg] of Object.entries(getSharedUiDeps(bosConfig))) { const version = catalog[name] ?? extractSemverExact(cfg.version) ?? extractSemverExact(cfg.requiredVersion); if (!version) continue; resolvedDeps[name] = { name, version, requiredVersion: caretRange(version), shareScope: cfg.shareScope ?? "default", singleton: cfg.singleton ?? false, eager: cfg.eager ?? false, strictVersion: cfg.strictVersion ?? false }; } const stableResolvedDeps = stableDepsObject(resolvedDeps); const resolved = { deps: stableResolvedDeps, fingerprintSha256: fingerprintResolved(stableResolvedDeps) }; const nextGenerated = { schemaVersion: 1, kind: "everything-dev/shared-ui", generatedAt: (/* @__PURE__ */ new Date()).toISOString(), ui: { deps: stableResolvedDeps, fingerprintSha256: resolved.fingerprintSha256 }, inputs: { mode, hostMode: opts.hostMode } }; let prevFingerprint = null; try { prevFingerprint = JSON.parse(readFileSync(generatedPath, "utf-8"))?.ui?.fingerprintSha256 ?? null; } catch {} mkdirSync(dirname(generatedPath), { recursive: true }); writeFileIfChanged(generatedPath, `${JSON.stringify(nextGenerated, null, 2)}\n`); const generatedChanged = prevFingerprint !== nextGenerated.ui.fingerprintSha256; return { mode, hostMode: opts.hostMode, bosConfigChanged, catalogChanged, generatedChanged, resolved }; } //#endregion export { syncAndGenerateSharedUi }; //# sourceMappingURL=shared.mjs.map