syncpack
Version:
Consistent dependency versions in large JavaScript Monorepos
54 lines (53 loc) • 1.55 kB
JavaScript
import { Effect, pipe } from 'effect';
import gt from 'semver/functions/gt.js';
import lt from 'semver/functions/lt.js';
import { clean } from './clean.js';
import { getRangeScore } from './get-range-score.js';
export function getPreferredVersion(preferVersion, specifiers) {
return pipe(
// every instance must have a semver version
Effect.all(specifiers.map(specifier => pipe(specifier.getSemver(), Effect.map(semver => ({ semver, specifier }))))),
// comparing semver can error on some loose ranges, all must succeed
Effect.map(semvers => semvers.sort((a, b) => compareSemver(a.semver, b.semver))),
// get the preferred value from the list
Effect.map(sorted => sorted[preferVersion === 'lowestSemver' ? 0 : sorted.length - 1]),
// return just the specifier
Effect.map(preferred => preferred?.specifier));
}
const EQ = 0;
const LT = -1;
const GT = 1;
function compareSemver(a, b) {
if (a.startsWith('workspace:')) {
return LT;
}
if (b.startsWith('workspace:')) {
return GT;
}
if (a === b) {
return EQ;
}
if (a === '*') {
return GT;
}
if (b === '*') {
return LT;
}
const cleanA = clean(a);
const cleanB = clean(b);
if (gt(cleanA, cleanB)) {
return GT;
}
if (lt(cleanA, cleanB)) {
return LT;
}
const scoreA = getRangeScore(a);
const scoreB = getRangeScore(b);
if (scoreA < scoreB) {
return LT;
}
if (scoreA > scoreB) {
return GT;
}
return EQ;
}