everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
158 lines (156 loc) • 5.17 kB
JavaScript
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import { dirname, join, relative } from "node:path";
import { glob } from "glob";
//#region src/internal/manifest-normalizer.ts
const FRAMEWORK_PACKAGES = ["every-plugin", "everything-dev"];
const CATALOG_TOOL_PACKAGES = [
"@rspack/core",
"@rspack/cli",
"@rsbuild/core",
"@rsbuild/plugin-react",
"@module-federation/enhanced",
"@module-federation/node",
"@module-federation/rsbuild-plugin",
"@module-federation/runtime-core",
"@module-federation/sdk",
"@module-federation/dts-plugin"
];
function readJson(filePath) {
return JSON.parse(readFileSync(filePath, "utf-8"));
}
function extractExactVersion(input) {
if (!input) return null;
const match = input.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/);
return match ? match[0] : null;
}
function writeJson(filePath, value) {
writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`);
}
function loadManifestNormalizationSpec(sourceRootDir) {
const rootCatalog = { ...readJson(join(sourceRootDir, "package.json")).workspaces?.catalog ?? {} };
const frameworkVersions = {};
for (const packageName of FRAMEWORK_PACKAGES) {
const sourcePackagePath = join(sourceRootDir, "packages", packageName, "package.json");
const localPackagePath = join(import.meta.dirname, "..", "..", packageName, "package.json");
const packageVersion = existsSync(localPackagePath) ? readJson(localPackagePath).version : existsSync(sourcePackagePath) ? readJson(sourcePackagePath).version : extractExactVersion(rootCatalog[packageName]);
if (!packageVersion) throw new Error(`Could not resolve version for ${packageName}`);
frameworkVersions[packageName] = packageVersion;
rootCatalog[packageName] = `^${packageVersion}`;
}
return {
rootCatalog,
frameworkVersions
};
}
function normalizeDependencyMap(map, spec, options) {
const catalogPackages = new Set([...FRAMEWORK_PACKAGES, ...CATALOG_TOOL_PACKAGES]);
let modified = false;
for (const [name, version] of Object.entries(map)) {
if (options.preserveCatalogRefs && catalogPackages.has(name)) {
if (version !== "catalog:") {
map[name] = "catalog:";
modified = true;
}
continue;
}
if (version === "workspace:*") {
const frameworkVersion = spec.frameworkVersions[name];
if (frameworkVersion) {
map[name] = `^${frameworkVersion}`;
modified = true;
continue;
}
if (options.removeWorkspaceDeps?.includes(name)) {
delete map[name];
modified = true;
}
continue;
}
if (options.resolveCatalogRefs && version.startsWith("catalog:")) {
const resolved = spec.rootCatalog[name];
if (resolved) {
map[name] = resolved;
modified = true;
}
}
}
return modified;
}
function normalizePackageManifest(pkg, spec, options) {
let modified = false;
for (const depField of [
"dependencies",
"devDependencies",
"peerDependencies"
]) {
const deps = pkg[depField];
if (!deps || typeof deps !== "object") continue;
if (normalizeDependencyMap(deps, spec, options)) modified = true;
}
if (pkg.workspaces && typeof pkg.workspaces === "object") {
const workspaces = pkg.workspaces;
if (options.excludeFrameworkWorkspaces && Array.isArray(workspaces.packages)) {
const nextPackages = workspaces.packages.filter((entry) => !FRAMEWORK_PACKAGES.some((name) => entry === `packages/${name}`));
if (nextPackages.length !== workspaces.packages.length) {
workspaces.packages = nextPackages;
modified = true;
}
}
if (workspaces.catalog && typeof workspaces.catalog === "object") for (const [name, version] of Object.entries(workspaces.catalog)) {
const resolved = spec.rootCatalog[name];
if (resolved && resolved !== version) {
workspaces.catalog[name] = resolved;
modified = true;
continue;
}
if (version === "workspace:*" && spec.frameworkVersions[name]) {
workspaces.catalog[name] = `^${spec.frameworkVersions[name]}`;
modified = true;
}
}
}
if (options.removeWorkspaces && "workspaces" in pkg) {
delete pkg.workspaces;
modified = true;
}
if (options.removePublishScripts && pkg.scripts && typeof pkg.scripts === "object") {
const scripts = pkg.scripts;
let scriptsModified = false;
for (const key of [
"prepublishOnly",
"prepack",
"prepare",
"postpack"
]) if (key in scripts) {
delete scripts[key];
scriptsModified = true;
}
if (scriptsModified) {
modified = true;
if (Object.keys(scripts).length === 0) delete pkg.scripts;
}
}
return modified;
}
async function normalizePackageManifestsInTree(opts) {
const spec = loadManifestNormalizationSpec(opts.sourceRootDir);
const files = await glob("**/package.json", {
cwd: opts.targetDir,
nodir: true,
dot: false,
absolute: true,
ignore: ["**/node_modules/**"]
});
const updatedFiles = [];
for (const filePath of files) {
const pkg = readJson(filePath);
if (normalizePackageManifest(pkg, spec, opts)) {
writeJson(filePath, pkg);
updatedFiles.push(filePath);
}
}
return updatedFiles;
}
//#endregion
export { loadManifestNormalizationSpec, normalizePackageManifestsInTree };
//# sourceMappingURL=manifest-normalizer.mjs.map