libyear
Version:
A simple measure of software dependency freshness
76 lines (75 loc) • 3.14 kB
JavaScript
import { default as chalk } from "chalk";
import { metrics } from "./constants.js";
import { printFloat } from "./numbers.js";
import { getTotals, getViolations } from "./validate.js";
const ntext = (text, plural, count) => Math.abs(count) === 1 ? text : plural;
const getMetricUnit = (metric, count) => {
switch (metric) {
case "releases":
case "major":
case "minor":
case "patch":
return ntext("release", "releases", count);
case "drift":
case "pulse":
default:
return ntext("libyear", "libyears", count);
}
};
const printIndividual = (violations) => {
violations.forEach((dependencies, metric) => {
dependencies.forEach(({ threshold, value }, dependency) => {
console.error(`${chalk.magenta(metric)}: ${chalk.cyan(dependency)} is ${chalk.red(`${printFloat(value)} ${getMetricUnit(metric, value)}`)} behind; threshold is ${chalk.yellow(printFloat(threshold))}.`);
});
});
};
const printCollective = (totals, violations, threshold) => {
const isBreach = (metric) => violations.has(metric);
const logger = (metric) => isBreach(metric) ? console.error : console.log;
const message = (metric, value, limit) => {
const valueStyler = isBreach(metric) ? chalk.red : chalk.greenBright;
const valueMessage = `${chalk.magenta(metric)}: ${{
drift: "package is",
pulse: "dependencies are",
releases: "dependencies are",
major: "dependencies are",
minor: "dependencies are",
patch: "dependencies are",
}[metric]} ${valueStyler(`${printFloat(value)} ${getMetricUnit(metric, value)}`)} behind`;
const limitMessage = `threshold is ${chalk.yellow(printFloat(limit))}`;
return isBreach(metric)
? `${valueMessage}; ${limitMessage}.`
: `${valueMessage}.`;
};
metrics.forEach((metric) => {
logger(metric)(message(metric, totals.get(metric), threshold?.[`${metric}Collective`]));
});
};
export const print = (dependencies, threshold, overrides) => {
console.table(dependencies.map(({ dependency, drift, pulse, releases, major, minor, patch, available, }) => ({
dependency,
drift: printFloat(drift),
pulse: printFloat(pulse),
releases,
major,
minor,
patch,
available,
})));
console.log();
const totals = getTotals(dependencies);
const violations = getViolations(dependencies, totals, threshold, overrides);
const hasIndividualViolations = Array.from(violations.individual.values()).reduce((acc, cur) => acc + cur.size, 0) > 0;
const hasCollectiveViolations = violations.collective.size > 0;
if (hasIndividualViolations) {
console.log(chalk.bold("# Individual"));
printIndividual(violations.individual);
console.log();
}
console.log(chalk.bold("# Collective"));
printCollective(totals, violations.collective, threshold);
console.log();
if (hasIndividualViolations || hasCollectiveViolations) {
process.exit(1);
}
};