yarn-berry-deduplicate
Version:
Deduplication tool for yarn.lock files
89 lines • 4.68 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.selectBestVersionFromPackageInstances = exports.computePackageInstances = void 0;
const tslib_1 = require("tslib");
const semver_1 = tslib_1.__importDefault(require("semver"));
const computePackageInstances = (packages, packageKey, { strategy = 'fewerHighest', includePrerelease = false, } = {}) => {
// Instances of this package in the tree
const packageInstances = packages[packageKey];
// Extract the list of unique versions for this package
const versions = new Map();
for (const packageInstance of packageInstances) {
if (packageInstance.ignored)
continue;
if (versions.has(packageInstance.installedVersion))
continue;
versions.set(packageInstance.installedVersion, {
pkg: packageInstance.pkg,
satisfies: new Set(),
});
}
// Link each package instance with all the versions it could satisfy.
for (const [version, { satisfies }] of versions) {
packageInstances.forEach((packageInstance) => {
// We can assume that the installed version always satisfied the requested version.
packageInstance.satisfiedBy.add(packageInstance.installedVersion);
// In some cases the requested version is invalid form a semver point of view (for
// example `sinon@next`). Just ignore those cases, they won't get deduped.
if (semver_1.default.validRange(packageInstance.requestedVersion, { includePrerelease }) &&
semver_1.default.satisfies(version, packageInstance.requestedVersion, { includePrerelease })) {
satisfies.add(packageInstance);
packageInstance.satisfiedBy.add(version);
}
});
}
;
// Sort the list of satisfied versions
packageInstances.forEach((packageInstance) => {
if (packageInstance.ignored) {
packageInstance.bestVersion = packageInstance.installedVersion;
return;
}
// Save all versions for future reference
packageInstance.versions = versions;
// Compute the versions that actually satisfy this instance
packageInstance.candidateVersions = Array.from(packageInstance.satisfiedBy);
packageInstance.candidateVersions.sort((versionA, versionB) => {
if (strategy === 'fewer' || strategy === 'mostCommon' || strategy === 'fewerHighest') {
// Sort versions based on how many packages it satisfies. In case of a tie, put the
// highest version first.
const satisfiesA = versions.get(versionA).satisfies;
const satisfiesB = versions.get(versionB).satisfies;
if (satisfiesB.size > satisfiesA.size)
return 1;
if (satisfiesB.size < satisfiesA.size)
return -1;
}
return semver_1.default.rcompare(versionA, versionB);
});
// The best package is always the first one in the list thanks to the sorting above.
packageInstance.bestVersion = packageInstance.candidateVersions[0];
});
return packageInstances;
};
exports.computePackageInstances = computePackageInstances;
const selectBestVersionFromPackageInstances = (packageInstances) => {
// Find the versions that were selected on the previous run
const selectedVersions = new Map();
packageInstances.forEach((packageInstance) => {
if (!selectedVersions.has(packageInstance.packageKey)) {
selectedVersions.set(packageInstance.packageKey, new Set());
}
selectedVersions.get(packageInstance.packageKey).add(packageInstance.bestVersion);
});
// Sort the list of satisfied versions
packageInstances.forEach((packageInstance) => {
if (packageInstance.ignored || !packageInstance.candidateVersions) {
return;
}
const selectedVersionsForPackage = selectedVersions.get(packageInstance.packageKey);
const candidateVersionsExcludingNotSelected = packageInstance.candidateVersions.filter(version => selectedVersionsForPackage.has(version));
candidateVersionsExcludingNotSelected.sort((versionA, versionB) => {
return semver_1.default.rcompare(versionA, versionB);
});
// The best package is always the first one in the list thanks to the sorting above.
packageInstance.bestVersion = candidateVersionsExcludingNotSelected[0];
});
};
exports.selectBestVersionFromPackageInstances = selectBestVersionFromPackageInstances;
//# sourceMappingURL=computePackageInstances.js.map