renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
148 lines (147 loc) • 6.95 kB
JavaScript
import { escapeRegExp, regEx } from "../../../../../util/regex.js";
import { matchAt, replaceAt } from "../../../../../util/string.js";
import { logger } from "../../../../../logger/index.js";
import "../../dep-types.js";
import { getNewGitValue, getNewNpmAliasValue } from "./common.js";
import { updatePnpmWorkspaceDependency } from "./pnpm.js";
import { updateYarnrcCatalogDependency } from "./yarn.js";
import { isArray, isNonEmptyStringAndNotWhitespace } from "@sindresorhus/is";
import { dequal } from "dequal";
//#region lib/modules/manager/npm/update/dependency/index.ts
function renameObjKey(oldObj, oldKey, newKey) {
return Object.keys(oldObj).reduce((acc, key) => {
if (key === oldKey) acc[newKey] = oldObj[oldKey];
else acc[key] = oldObj[key];
return acc;
}, {});
}
function replaceAsString(parsedContents, fileContent, depType, depName, oldValue, newValue, parents) {
if (depType === "packageManager") parsedContents[depType] = newValue;
else if (depType === "pnpm.overrides") parsedContents.pnpm.overrides[depName] = newValue;
else if (depName === oldValue) delete Object.assign(parsedContents[depType], { [newValue]: parsedContents[depType][oldValue] })[oldValue];
else if (depType === "dependenciesMeta") {
// v8 ignore else -- TODO: add test #40625
if (oldValue !== newValue) parsedContents.dependenciesMeta = renameObjKey(parsedContents.dependenciesMeta, oldValue, newValue);
} else if (parents && depType === "overrides") {
const { depObjectReference, overrideDepName } = overrideDepPosition(parsedContents[depType], parents, depName);
// v8 ignore else -- TODO: add test #40625
if (depObjectReference) depObjectReference[overrideDepName] = newValue;
} else parsedContents[depType][depName] = newValue;
const searchString = `"${oldValue}"`;
let newString = `"${newValue}"`;
const match = regEx(`^(patch:${escapeRegExp(depName)}@(npm:)?).*#`).exec(oldValue);
if (match && depType === "resolutions") {
const patch = oldValue.replace(match[0], `${match[1]}${newValue}#`);
parsedContents[depType][depName] = patch;
newString = `"${patch}"`;
}
let searchIndex = fileContent.indexOf(`"${depType}"`) + depType.length;
logger.trace(`Starting search at index ${searchIndex}`);
for (; searchIndex < fileContent.length; searchIndex += 1) if (matchAt(fileContent, searchIndex, searchString)) {
logger.trace(`Found match at index ${searchIndex}`);
const testContent = replaceAt(fileContent, searchIndex, searchString, newString);
if (dequal(parsedContents, JSON.parse(testContent))) return testContent;
}
// v8 ignore next -- TODO: add test #40625
throw new Error();
}
function updateDependency({ fileContent, packageFile: packageFileName, upgrade }) {
if (upgrade.depType?.startsWith("pnpm.catalog") || upgrade.depType === "pnpm-workspace.overrides") return updatePnpmWorkspaceDependency({
fileContent,
packageFile: packageFileName,
upgrade
});
if (upgrade.depType?.startsWith("yarn.catalog")) return updateYarnrcCatalogDependency({
fileContent,
packageFile: packageFileName,
upgrade
});
const { depType, managerData } = upgrade;
const depName = managerData?.key ?? upgrade.depName;
let { newValue } = upgrade;
newValue = getNewGitValue(upgrade) ?? newValue;
newValue = getNewNpmAliasValue(newValue, upgrade) ?? newValue;
logger.debug(`npm.updateDependency(): ${depType}.${depName} = ${newValue}`);
try {
const parsedContents = JSON.parse(fileContent);
let overrideDepParents = void 0;
let oldVersion;
if (depType === "packageManager") {
oldVersion = parsedContents[depType];
newValue = `${depName}@${newValue}`;
} else if (isOverrideObject(upgrade)) {
overrideDepParents = managerData?.parents;
// v8 ignore else -- TODO: add test #40625
if (overrideDepParents) {
const { depObjectReference, overrideDepName } = overrideDepPosition(parsedContents.overrides, overrideDepParents, depName);
// v8 ignore else -- TODO: add test #40625
if (depObjectReference) oldVersion = depObjectReference[overrideDepName];
}
} else if (depType === "pnpm.overrides") oldVersion = parsedContents.pnpm?.overrides?.[depName];
else oldVersion = parsedContents[depType][depName];
if (oldVersion === newValue) {
logger.trace("Version is already updated");
return fileContent;
}
let newFileContent;
if (upgrade.newName && upgrade.replacementApproach === "alias") newFileContent = replaceAsString(parsedContents, fileContent, depType, depName, oldVersion, `npm:${upgrade.newName}@${newValue}`, overrideDepParents);
else {
newFileContent = replaceAsString(parsedContents, fileContent, depType, depName, oldVersion, newValue, overrideDepParents);
if (upgrade.newName) newFileContent = replaceAsString(parsedContents, newFileContent, depType, depName, depName, upgrade.newName, overrideDepParents);
}
/* v8 ignore next -- needs test */
if (!newFileContent) {
logger.debug({
fileContent,
parsedContents,
depType,
depName,
newValue
}, "Warning: updateDependency error");
return fileContent;
}
if (parsedContents?.resolutions) {
let depKey;
if (parsedContents.resolutions[depName]) depKey = depName;
else if (parsedContents.resolutions[`**/${depName}`]) depKey = `**/${depName}`;
if (depKey) {
/* v8 ignore next -- needs test */
if (parsedContents.resolutions[depKey] !== oldVersion) logger.debug({
depName,
depKey,
oldVersion,
resolutionsVersion: parsedContents.resolutions[depKey]
}, "Upgraded dependency exists in yarn resolutions but is different version");
newFileContent = replaceAsString(parsedContents, newFileContent, "resolutions", depKey, parsedContents.resolutions[depKey], newValue);
if (upgrade.newName) {
if (depKey === `**/${depName}`) upgrade.newName = `**/${upgrade.newName}`;
newFileContent = replaceAsString(parsedContents, newFileContent, "resolutions", depKey, depKey, upgrade.newName);
}
}
}
if (parsedContents?.dependenciesMeta) {
for (const [depKey] of Object.entries(parsedContents.dependenciesMeta)) if (depKey.startsWith(`${depName}@`)) newFileContent = replaceAsString(parsedContents, newFileContent, "dependenciesMeta", depName, depKey, `${depName}@${newValue}`);
}
return newFileContent;
} catch (err) {
logger.debug({ err }, "updateDependency error");
return null;
}
}
function overrideDepPosition(overrideBlock, parents, depName) {
const lastParent = parents[parents.length - 1];
let overrideDep = overrideBlock;
for (const parent of parents)
// v8 ignore else -- TODO: add test #40625
if (overrideDep) overrideDep = overrideDep[parent];
return {
depObjectReference: overrideDep,
overrideDepName: depName === lastParent ? "." : depName
};
}
function isOverrideObject(upgrade) {
return isArray(upgrade.managerData?.parents, isNonEmptyStringAndNotWhitespace) && upgrade.depType === "overrides";
}
//#endregion
export { updateDependency };
//# sourceMappingURL=index.js.map