UNPKG

everything-dev

Version:

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

231 lines (229 loc) • 8.83 kB
import { readAuthoredConfigInput } from "../resolution/load.mjs"; import { getExtendsRef } from "../../utils/bos-ref.mjs"; import { readWorkspaceCatalog, writeWorkspaceCatalog } from "../workspace/catalog.mjs"; import { findWorkspaceRoot } from "../workspace/workspace.mjs"; import { readInstalledFrameworkVersion } from "../framework-version.mjs"; import { buildChildRootScripts, getParentOnlyScriptKeys } from "./init.mjs"; import { readJsonFile } from "../../utils/json-file.mjs"; import { existsSync, statSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { glob } from "glob"; //#region src/services/scaffold/upgrade-packages.ts const FRAMEWORK_PACKAGES = ["everything-dev", "every-plugin"]; const AUTH_CORE_PACKAGE = "@better-auth/core"; const AUTH_CORE_TRIGGER_PACKAGES = [ "better-auth", "better-near-auth", "@better-auth/api-key", "@better-auth/passkey" ]; function workspaceDirOf(projectDir) { return findWorkspaceRoot(projectDir)?.dir ?? projectDir; } function readRootPackageJson(projectDir) { return readJsonFile(join(workspaceDirOf(projectDir), "package.json")); } function readRootCatalogEntry(projectDir, packageName) { return readWorkspaceCatalog(workspaceDirOf(projectDir))[packageName]; } /** * Chain-catalog vs local-catalog diff for the drift alarm (ADR 0034 pt 6): * entries only count when the local catalog actually pins a different version * (`from !== undefined`) — a purely-additive chain entry the child does not * consume is not drift. Reading the local catalog is `readWorkspaceCatalog` * (pnpm-workspace.yaml first, package.json fallback) — the v1 package.json-only * read made every entry read as new on v2 children, a permanent false positive. */ function diffCatalogEntries(sourceRootCatalog, currentCatalogEntries) { const updates = []; for (const [name, targetVersion] of Object.entries(sourceRootCatalog)) { if (FRAMEWORK_PACKAGES.includes(name)) continue; const currentVersion = currentCatalogEntries[name]; if (currentVersion === targetVersion) continue; updates.push({ name, from: currentVersion, to: targetVersion }); } return updates; } function readCurrentPackageSpecifier(projectDir, packageName) { const pkg = readRootPackageJson(projectDir); for (const fieldName of [ "dependencies", "devDependencies", "peerDependencies" ]) { const value = pkg[fieldName]?.[packageName]; if (!value) continue; if (value === "catalog:") return readRootCatalogEntry(projectDir, packageName) ?? readInstalledVersion(projectDir, packageName); if (value.startsWith("workspace:") || value.startsWith("file:") || value.startsWith("link:")) return readInstalledVersion(projectDir, packageName); return value; } return readRootCatalogEntry(projectDir, packageName) ?? readInstalledVersion(projectDir, packageName); } function setCatalogRefs(field, packageNames) { if (!field) return false; let modified = false; for (const packageName of packageNames) if (setCatalogRef(field, packageName)) modified = true; return modified; } function syncPackageObjectCatalogRefs(pkg, packageNames) { let modified = false; for (const fieldName of [ "dependencies", "devDependencies", "peerDependencies" ]) { const field = pkg[fieldName]; if (setCatalogRefs(field, packageNames)) modified = true; } return modified; } function findPackageFieldWithAnyDependency(pkg, packageNames) { for (const fieldName of [ "dependencies", "devDependencies", "peerDependencies" ]) { const field = pkg[fieldName]; if (!field) continue; if (packageNames.some((packageName) => typeof field[packageName] === "string")) return field; } } function packageObjectNeedsAuthCoreCatalogRef(pkg) { if (!findPackageFieldWithAnyDependency(pkg, AUTH_CORE_TRIGGER_PACKAGES)) return false; for (const fieldName of [ "dependencies", "devDependencies", "peerDependencies" ]) if (pkg[fieldName]?.["@better-auth/core"]) return false; return true; } function ensureAuthCoreCatalogRef(pkg) { if (!packageObjectNeedsAuthCoreCatalogRef(pkg)) return false; const targetField = findPackageFieldWithAnyDependency(pkg, AUTH_CORE_TRIGGER_PACKAGES); if (!targetField) return false; targetField[AUTH_CORE_PACKAGE] = "catalog:"; return true; } function packageObjectNeedsCatalogRefs(pkg, packageNames) { for (const fieldName of [ "dependencies", "devDependencies", "peerDependencies" ]) { const field = pkg[fieldName]; if (!field) continue; for (const packageName of packageNames) { const value = field[packageName]; if (!value) continue; if (value !== "catalog:" && !value.startsWith("file:") && !value.startsWith("link:")) return true; } } return false; } function packageFileNeedsCatalogRefs(filePath, packageNames) { return packageObjectNeedsCatalogRefs(readJsonFile(filePath), packageNames); } function updatePackageFileCatalogRefs(filePath, packageNames) { const pkg = readJsonFile(filePath); const modified = syncPackageObjectCatalogRefs(pkg, packageNames); if (modified) writeFileSync(filePath, `${JSON.stringify(pkg, null, 2)}\n`); return modified; } function updatePackageFileAuthCoreRef(filePath) { const pkg = readJsonFile(filePath); const modified = ensureAuthCoreCatalogRef(pkg); if (modified) writeFileSync(filePath, `${JSON.stringify(pkg, null, 2)}\n`); return modified; } function syncRootCatalogWithParent(projectDir, parentCatalog) { const workspaceDir = workspaceDirOf(projectDir); const pkgPath = join(workspaceDir, "package.json"); const pkg = readJsonFile(pkgPath); const modified = syncPackageObjectCatalogRefs(pkg, Object.keys(parentCatalog)); let catalogChanged = false; const catalog = readWorkspaceCatalog(workspaceDir); for (const [packageName, version] of Object.entries(parentCatalog)) if (catalog[packageName] !== version) { catalog[packageName] = version; catalogChanged = true; } if (catalogChanged) writeWorkspaceCatalog(workspaceDir, catalog); if (modified) writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`); return modified || catalogChanged; } function readInstalledVersion(projectDir, packageName) { return readInstalledFrameworkVersion(projectDir, packageName); } function setCatalogRef(field, packageName) { if (!field || !(packageName in field)) return false; if (field[packageName] === "catalog:" || field[packageName].startsWith("file:")) return false; field[packageName] = "catalog:"; return true; } async function findWorkspacePackageJsons(projectDir) { const root = findWorkspaceRoot(projectDir); if (!root) return []; const pkgPaths = []; for (const member of root.members) { const pkgPath = join(member.dir, "package.json"); if (existsSync(pkgPath) && statSync(pkgPath).isFile()) pkgPaths.push(pkgPath); } return [...new Set(pkgPaths)]; } async function migrateChildRootPackageJson(projectDir) { const config = await readAuthoredConfigInput(projectDir); const pkgPath = join(workspaceDirOf(projectDir), "package.json"); if (!config || !existsSync(pkgPath)) return false; if (!getExtendsRef(config)?.startsWith("bos://")) return false; const pkg = readJsonFile(pkgPath); let changed = false; if (pkg.private !== true) { pkg.private = true; changed = true; } if (pkg.type !== "module") { pkg.type = "module"; changed = true; } if ("module" in pkg) { delete pkg.module; changed = true; } const pluginPackageJsons = await glob("plugins/*/package.json", { cwd: projectDir, nodir: true, dot: false, absolute: false }); const childScripts = buildChildRootScripts({ ui: existsSync(join(projectDir, "ui", "package.json")), api: existsSync(join(projectDir, "api", "package.json")), host: existsSync(join(projectDir, "host", "package.json")), plugins: pluginPackageJsons.length > 0 }); if (!pkg.scripts || typeof pkg.scripts !== "object") { pkg.scripts = {}; changed = true; } const scripts = pkg.scripts; for (const [key, value] of Object.entries(childScripts)) if (scripts[key] !== value) { scripts[key] = value; changed = true; } for (const obsoleteScript of [ ...getParentOnlyScriptKeys(projectDir), "sync-catalog", "init" ]) if (obsoleteScript in scripts) { delete scripts[obsoleteScript]; changed = true; } if (changed) writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`); return changed; } //#endregion export { 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 }; //# sourceMappingURL=upgrade-packages.mjs.map