everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
178 lines (176 loc) • 9.02 kB
JavaScript
import { readWorkspaceCatalog } from "../workspace/catalog.mjs";
import { timePhase } from "../../utils/timing.mjs";
import { runPnpmInstallForUpgrade } from "./init.mjs";
import { syncTemplate } from "./sync.mjs";
import { readJsonFile } from "../../utils/json-file.mjs";
import { AUTH_CORE_PACKAGE, AUTH_CORE_TRIGGER_PACKAGES, FRAMEWORK_PACKAGES, diffCatalogEntries, ensureAuthCoreCatalogRef, findWorkspacePackageJsons, migrateChildRootPackageJson, packageFileNeedsCatalogRefs, packageObjectNeedsAuthCoreCatalogRef, packageObjectNeedsCatalogRefs, readCurrentPackageSpecifier, readInstalledVersion, readRootCatalogEntry, readRootPackageJson, setCatalogRef, syncRootCatalogWithParent, updatePackageFileAuthCoreRef, updatePackageFileCatalogRefs, workspaceDirOf } from "./upgrade-packages.mjs";
import { buildChangelogUrl, loadParentPluginOptions, readExtendedRootSource } from "./upgrade-source.mjs";
import { applyPlatformPin, describeMigrationFailure, runMigrationPhase, stampPlatformPin } from "./upgrade-migration.mjs";
import { existsSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { spawnSync } from "node:child_process";
import process from "node:process";
//#region src/services/scaffold/upgrade.ts
const UPSTREAM_ISSUE_URL = "https://github.com/NEARBuilders/everything-dev/issues";
async function upgradeTemplate(projectDir, options) {
const timings = [];
if (options.check) options.dryRun = true;
const pkgPath = join(workspaceDirOf(projectDir), "package.json");
if (!existsSync(pkgPath)) return {
status: "error",
packages: [],
timings,
error: "No package.json found in current directory"
};
const parentSource = await readExtendedRootSource(projectDir);
const sourceRootCatalog = parentSource.catalog;
const inheritedCatalogPackageNames = Object.keys(sourceRootCatalog);
const currentCatalogEntries = readWorkspaceCatalog(workspaceDirOf(projectDir));
const workspacePkgPaths = await findWorkspacePackageJsons(projectDir);
const hasCatalogRefRewrites = inheritedCatalogPackageNames.length > 0 && (packageObjectNeedsCatalogRefs(readRootPackageJson(projectDir), inheritedCatalogPackageNames) || workspacePkgPaths.some((pkgPath) => packageFileNeedsCatalogRefs(pkgPath, inheritedCatalogPackageNames)));
const hasAuthCoreRefRewrites = packageObjectNeedsAuthCoreCatalogRef(readRootPackageJson(projectDir)) || workspacePkgPaths.some((pkgPath) => packageObjectNeedsAuthCoreCatalogRef(readJsonFile(pkgPath)));
const { packages, catalogVersionUpdates } = await timePhase(timings, "check package versions", async () => {
const nextPackages = [];
for (const name of FRAMEWORK_PACKAGES) {
const current = readCurrentPackageSpecifier(projectDir, name);
const target = sourceRootCatalog[name] ?? current ?? "unknown";
nextPackages.push({
name,
from: current,
to: target
});
}
return {
packages: nextPackages,
catalogVersionUpdates: diffCatalogEntries(sourceRootCatalog, currentCatalogEntries)
};
});
const hasFrameworkUpdates = packages.some((p) => p.from !== p.to && p.from !== void 0);
const hasCatalogUpdates = catalogVersionUpdates.some((u) => u.from !== void 0);
const hasUpdates = hasFrameworkUpdates || hasCatalogUpdates || hasCatalogRefRewrites || hasAuthCoreRefRewrites;
if (options.dryRun) {
let changelogUrl;
const pluginOptions = options.noSync ? null : await timePhase(timings, "list parent plugins", () => loadParentPluginOptions(projectDir));
if (hasUpdates) {
const mainPkg = packages.find((p) => p.name === "everything-dev");
if (mainPkg?.from && mainPkg.from !== mainPkg.to) changelogUrl = buildChangelogUrl(mainPkg.from, mainPkg.to, parentSource.repository);
}
return {
status: "dry-run",
packages: [...packages, ...catalogVersionUpdates.map((u) => ({
name: u.name,
from: u.from,
to: u.to
}))],
availablePlugins: pluginOptions?.newPluginKeys,
platform: {
resolved: parentSource.platform.manifest.frameworkVersion,
source: `bos://${parentSource.platform.source.account}/${parentSource.platform.source.gateway}`,
fromCache: parentSource.platform.fromCache
},
updatesAvailable: hasUpdates,
timings,
changelogUrl
};
}
const targetMainVersion = packages.find((p) => p.name === "everything-dev")?.to;
const versionDelta = options.migrationsOnly && !options.from ? false : options.from !== void 0 && targetMainVersion !== void 0 ? options.from !== targetMainVersion : hasFrameworkUpdates;
if (options.migrationsOnly) return await runMigrationPhase(projectDir, options, parentSource, { versionDelta });
if (versionDelta && !options.noSync && !options.force) {
const preflight = await timePhase(timings, "preflight template sync", () => syncTemplate(projectDir, { dryRun: true }));
if (preflight.status === "conflicted" || (preflight.conflicted?.length ?? 0) > 0) return {
status: "error",
packages,
timings,
error: `Template files conflict with the upstream release — nothing was applied. Review the conflicts or run \`bos upgrade --force\` to overwrite (current copies are backed up). To make a local change permanent, file an issue: ${UPSTREAM_ISSUE_URL}. Conflicted: ${(preflight.conflicted ?? []).join(", ")}`
};
}
await timePhase(timings, "apply package updates", async () => {
if (inheritedCatalogPackageNames.length > 0) syncRootCatalogWithParent(projectDir, sourceRootCatalog);
if (inheritedCatalogPackageNames.length > 0) for (const pkgPath of workspacePkgPaths) updatePackageFileCatalogRefs(pkgPath, inheritedCatalogPackageNames);
const rootPkgPath = join(workspaceDirOf(projectDir), "package.json");
const rootPkg = readJsonFile(rootPkgPath);
if (ensureAuthCoreCatalogRef(rootPkg)) writeFileSync(rootPkgPath, `${JSON.stringify(rootPkg, null, 2)}\n`);
for (const pkgPath of workspacePkgPaths) updatePackageFileAuthCoreRef(pkgPath);
});
const needsInstall = (hasUpdates || hasCatalogUpdates) && !options.noInstall;
if (needsInstall) await timePhase(timings, "install dependencies", () => runPnpmInstallForUpgrade(workspaceDirOf(projectDir)));
if (needsInstall && hasFrameworkUpdates) {
const bosPath = join(workspaceDirOf(projectDir), "node_modules", ".bin", "bos");
const childArgs = [
"upgrade",
"--migrations-only",
"--no-install",
"--from",
packages.find((p) => p.name === "everything-dev")?.from ?? "unknown",
...options.noSync ? ["--no-sync"] : [],
...options.force ? ["--force"] : [],
"--json"
];
const childResult = spawnSync(bosPath, childArgs, {
cwd: projectDir,
stdio: [
"inherit",
"pipe",
"pipe"
],
encoding: "utf-8",
env: {
...process.env,
BOS_NO_BANNER: "1"
}
});
if (childResult.status !== 0) return {
status: "error",
packages: [...packages, ...catalogVersionUpdates.map((u) => ({
name: u.name,
from: u.from,
to: u.to
}))],
timings,
error: `Migration phase failed: ${describeMigrationFailure(childResult.stdout, childResult.stderr)}`
};
try {
const childUpgrade = JSON.parse(childResult.stdout);
const mainPkg = packages.find((p) => p.name === "everything-dev");
const changelogUrl = mainPkg?.from && mainPkg.from !== mainPkg.to ? buildChangelogUrl(mainPkg.from, mainPkg.to, parentSource.repository) : void 0;
return {
...childUpgrade,
packages: [...packages, ...catalogVersionUpdates.map((u) => ({
name: u.name,
from: u.from,
to: u.to
}))],
timings: [...timings, ...childUpgrade.timings ?? []],
changelogUrl
};
} catch {
return {
status: "error",
packages: [...packages, ...catalogVersionUpdates.map((u) => ({
name: u.name,
from: u.from,
to: u.to
}))],
timings,
error: "Failed to parse migration phase output"
};
}
}
const migrationResult = await runMigrationPhase(projectDir, options, parentSource, { versionDelta });
const mainPkg = packages.find((p) => p.name === "everything-dev");
const changelogUrl = mainPkg?.from && mainPkg.from !== mainPkg.to ? buildChangelogUrl(mainPkg.from, mainPkg.to, parentSource.repository) : void 0;
return {
...migrationResult,
packages: [...packages, ...catalogVersionUpdates.map((u) => ({
name: u.name,
from: u.from,
to: u.to
}))],
timings: [...timings, ...migrationResult.timings ?? []],
changelogUrl
};
}
//#endregion
export { AUTH_CORE_PACKAGE, AUTH_CORE_TRIGGER_PACKAGES, FRAMEWORK_PACKAGES, applyPlatformPin, buildChangelogUrl, describeMigrationFailure, diffCatalogEntries, ensureAuthCoreCatalogRef, findWorkspacePackageJsons, loadParentPluginOptions, migrateChildRootPackageJson, packageFileNeedsCatalogRefs, packageObjectNeedsAuthCoreCatalogRef, packageObjectNeedsCatalogRefs, readCurrentPackageSpecifier, readExtendedRootSource, readInstalledVersion, readRootCatalogEntry, readRootPackageJson, runMigrationPhase, setCatalogRef, stampPlatformPin, syncRootCatalogWithParent, updatePackageFileAuthCoreRef, updatePackageFileCatalogRefs, upgradeTemplate, workspaceDirOf };
//# sourceMappingURL=upgrade.mjs.map