renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
236 lines (235 loc) • 9.26 kB
JavaScript
import { regEx } from "../../../util/regex.js";
import { logger } from "../../../logger/index.js";
import api$1 from "../npm/index.js";
import { isNumber } from "@sindresorhus/is";
import semver from "semver";
import { parseRange } from "semver-utils";
//#region lib/modules/versioning/composer/index.ts
const id = "composer";
function getVersionParts(input) {
const versionParts = input.split("-");
if (versionParts.length === 1) return [input, ""];
return [versionParts[0], `-${versionParts[1]}`];
}
function padZeroes(input) {
const [output, stability] = getVersionParts(input);
const sections = output.split(".");
while (sections.length < 3) sections.push("0");
return `${sections.join(".")}${stability}`;
}
function convertStabilityModifier(input) {
const versionParts = input.split("@");
if (versionParts.length === 1) return input;
const stability = versionParts[1].replace(regEx(/(?:^|\s)(beta|alpha|rc)([1-9][0-9]*)(?: |$)/gi), "$1.$2");
return `${padZeroes(versionParts[0])}-${stability}`;
}
function normalizeVersion(input) {
let output = input;
output = output.replace(regEx(/^\+/), "");
output = output.replace(regEx(/(^|>|>=|\^|~)v/i), "$1");
return convertStabilityModifier(output);
}
/**
* @param versions Version list in any format, it recognizes the specific patch format x.x.x-pXX
* @param range Range in composer format
* @param minMode If true, it will calculate minSatisfyingVersion, if false, it calculates the maxSatisfyingVersion
* @returns min or max satisfyingVersion from the input
*/
function calculateSatisfyingVersionIntenal(versions, range, minMode) {
const versionsMapped = versions.map((x) => {
return {
origianl: x,
cleaned: removeComposerSpecificPatchPart(x),
npmVariant: composer2npm(removeComposerSpecificPatchPart(x)[0])
};
});
const npmVersions = versionsMapped.map((x) => x.npmVariant);
const npmVersion = minMode ? api$1.minSatisfyingVersion(npmVersions, composer2npm(range)) : api$1.getSatisfyingVersion(npmVersions, composer2npm(range));
if (!npmVersion) return null;
return versionsMapped.filter((x) => x.npmVariant === npmVersion).sort((a, b) => (minMode ? 1 : -1) * sortVersions(a.origianl, b.origianl))[0].origianl;
}
/**
* @param intput Version in any format, it recognizes the specific patch format x.x.x-pXX
* @returns If input contains the specific patch, it returns the input with removed the patch and true, otherwise it retunrs the same string and false.
*/
function removeComposerSpecificPatchPart(input) {
const match = /^v?\d+(\.\d+(\.\d+(\.\d+)?)?)?(?<suffix>-p[1-9]\d*)$/gi.exec(input);
return match ? [input.replace(match.groups.suffix, ""), true] : [input, false];
}
function composer2npm(input) {
return input.split(regEx(/\s*\|\|?\s*/g)).map((part) => {
const cleanInput = normalizeVersion(part);
if (api$1.isVersion(cleanInput)) return cleanInput;
if (api$1.isVersion(padZeroes(cleanInput))) return padZeroes(cleanInput);
const [versionId, stability] = getVersionParts(cleanInput);
let output = versionId;
output = output.replace(regEx(/(?:^|\s)~([1-9][0-9]*(?:\.[0-9]*)?)(?: |$)/g), "^$1");
output = output.replace(regEx(/(?:^|\s)~(0\.[1-9][0-9]*)(?: |$)/g), ">=$1 <1");
output = output.replace(regEx(/^(<\d+(\.\d+)?)$/g), "$1.0").replace(regEx(/^(<\d+(\.\d+)?)$/g), "$1.0");
return output + stability;
}).map((part) => part.replace(/([a-z])([0-9])/gi, "$1.$2")).join(" || ");
}
function equals(a, b) {
return api$1.equals(composer2npm(a), composer2npm(b));
}
function getMajor(version) {
const semverVersion = semver.coerce(composer2npm(version));
return semverVersion ? api$1.getMajor(semverVersion) : null;
}
function getMinor(version) {
const semverVersion = semver.coerce(composer2npm(version));
return semverVersion ? api$1.getMinor(semverVersion) : null;
}
function getPatch(version) {
const semverVersion = semver.coerce(composer2npm(version));
return semverVersion ? api$1.getPatch(semverVersion) : null;
}
function isGreaterThan(a, b) {
return sortVersions(a, b) === 1;
}
function isLessThanRange(version, range) {
return !!api$1.isLessThanRange?.(composer2npm(version), composer2npm(range));
}
function isSingleVersion(input) {
return !!input && api$1.isSingleVersion(composer2npm(input));
}
function isStable(version) {
if (version) {
const [withoutPatch] = removeComposerSpecificPatchPart(version);
return api$1.isStable(composer2npm(withoutPatch));
}
return false;
}
function isValid(input) {
return !!input && api$1.isValid(composer2npm(input));
}
function isVersion(input) {
return !!input && api$1.isVersion(composer2npm(input));
}
function matches(version, range) {
return api$1.matches(composer2npm(version), composer2npm(range));
}
function getSatisfyingVersion(versions, range) {
return calculateSatisfyingVersionIntenal(versions, range, false);
}
function minSatisfyingVersion(versions, range) {
return calculateSatisfyingVersionIntenal(versions, range, true);
}
function subset(subRange, superRange) {
try {
return api$1.subset(composer2npm(subRange), composer2npm(superRange));
} catch (err) {
logger.trace({ err }, "composer.subset error");
return false;
}
}
function intersects(subRange, superRange) {
try {
return api$1.intersects(composer2npm(subRange), composer2npm(superRange));
} catch (err) {
logger.trace({ err }, "composer.intersects error");
return false;
}
}
function getNewValue({ currentValue, rangeStrategy, currentVersion, newVersion }) {
if (rangeStrategy === "update-lockfile") {
if (matches(newVersion, currentValue)) return currentValue;
return getNewValue({
currentValue,
rangeStrategy: "replace",
currentVersion,
newVersion
});
}
const currentMajor = currentVersion ? getMajor(currentVersion) : null;
const toMajor = getMajor(newVersion);
const toMinor = getMinor(newVersion);
let newValue = null;
if (isVersion(currentValue)) newValue = newVersion;
else if (regEx(/^[~^](0\.[1-9][0-9]*)$/).test(currentValue)) {
const operator = currentValue.substring(0, 1);
if (toMajor === 0) newValue = `${operator}0.${toMinor}`;
else newValue = `${operator}${toMajor}.0`;
} else if (regEx(/^[~^]([0-9]*)$/).test(currentValue)) newValue = `${currentValue.substring(0, 1)}${toMajor}`;
else if (toMajor && regEx(/^[~^]([0-9]*(?:\.[0-9]*)?)$/).test(currentValue)) {
const operator = currentValue.substring(0, 1);
if (rangeStrategy === "bump") newValue = `${operator}${newVersion}`;
else if (isNumber(currentMajor) && toMajor > currentMajor || !toMinor) newValue = `${operator}${toMajor}.0`;
else newValue = `${operator}${toMajor}.${toMinor}`;
} else if (currentVersion && api$1.isVersion(padZeroes(normalizeVersion(newVersion))) && api$1.isValid(normalizeVersion(currentValue)) && composer2npm(currentValue) === normalizeVersion(currentValue)) newValue = api$1.getNewValue({
currentValue: normalizeVersion(currentValue),
rangeStrategy,
currentVersion: padZeroes(normalizeVersion(currentVersion)),
newVersion: padZeroes(normalizeVersion(newVersion))
});
if (rangeStrategy === "widen" && matches(newVersion, currentValue)) newValue = currentValue;
else if (currentValue.includes(" || ") || rangeStrategy === "widen") {
const splitValues = currentValue.split("||");
const lastValue = splitValues[splitValues.length - 1];
const replacementValue = getNewValue({
currentValue: lastValue.trim(),
rangeStrategy: "replace",
currentVersion,
newVersion
});
if (rangeStrategy === "replace") newValue = replacementValue;
else if (replacementValue) {
const parsedRange = parseRange(replacementValue);
const element = parsedRange[parsedRange.length - 1];
if (element.operator?.startsWith("<")) {
const splitCurrent = currentValue.split(element.operator);
splitCurrent.pop();
newValue = `${splitCurrent.join(element.operator)}${replacementValue}`;
} else newValue = `${currentValue} || ${replacementValue}`;
}
}
if (!newValue) {
logger.warn({
currentValue,
rangeStrategy,
currentVersion,
newVersion
}, "Unsupported composer value");
newValue = newVersion;
}
if (currentValue.split(".")[0].includes("v")) newValue = newValue.replace(regEx(/([0-9])/), "v$1");
if (currentValue.includes("@")) newValue += `@${currentValue.split("@")[1]}`;
return newValue;
}
function sortVersions(a, b) {
const [aWithoutPatch, aContainsPatch] = removeComposerSpecificPatchPart(a);
const [bWithoutPatch, bContainsPatch] = removeComposerSpecificPatchPart(b);
if (aContainsPatch === bContainsPatch) return api$1.sortVersions(composer2npm(a), composer2npm(b));
else if (api$1.equals(composer2npm(aWithoutPatch), composer2npm(bWithoutPatch))) return aContainsPatch ? 1 : -1;
else return api$1.sortVersions(composer2npm(a), composer2npm(b));
}
function isCompatible(version) {
return isVersion(version);
}
function isBreaking(current, version) {
return api$1.isBreaking(composer2npm(current), composer2npm(version));
}
const api = {
equals,
getMajor,
getMinor,
getPatch,
isBreaking,
isCompatible,
isGreaterThan,
isLessThanRange,
isSingleVersion,
isStable,
isValid,
isVersion,
matches,
getSatisfyingVersion,
minSatisfyingVersion,
getNewValue,
sortVersions,
subset,
intersects
};
//#endregion
export { api as default, id };
//# sourceMappingURL=index.js.map