libyear
Version:
A simple measure of software dependency freshness
53 lines (52 loc) • 2.22 kB
JavaScript
import { METRICS } from "./constants.js";
const isExcused = (dependency, overrides) => Object.entries(overrides).some(([pattern, { defer }]) => RegExp(pattern).test(dependency) &&
defer != null &&
Date.now() < Date.parse(defer));
const isBreach = (value, limit, dependency, overrides) => limit != null &&
value > limit &&
(dependency == null || !isExcused(dependency, overrides ?? {}));
const getMatchingPattern = (dependency, overrides) => Object.keys(overrides).find((pattern) => RegExp(pattern).test(dependency));
export const getTotals = (dependencies) => {
const totals = {};
dependencies.forEach((dependency) => {
METRICS.forEach((metric) => {
if (!Number.isNaN(dependency[metric])) {
const acc = Object.hasOwn(totals, metric) ? (totals[metric] ?? 0) : 0;
const cur = dependency[metric];
totals[metric] = acc + cur;
}
});
});
return totals;
};
const getCollectiveViolations = (totals, limits) => {
const violations = {};
METRICS.forEach((metric) => {
const value = totals[metric];
const limit = limits?.[`${metric}Collective`];
if (value != null && isBreach(value, limit)) {
violations[metric] = value;
}
});
return violations;
};
const getIndividualViolations = (dependencies, limits, overrides) => {
const violations = {};
dependencies.forEach(({ dependency, ...rest }) => {
METRICS.forEach((metric) => {
const value = rest[metric];
const limit = overrides?.[getMatchingPattern(dependency, overrides) ?? ""]?.[metric] ?? limits?.[`${metric}Individual`];
if (limit != null && isBreach(value, limit, dependency, overrides)) {
if (!Object.hasOwn(violations, metric)) {
violations[metric] = {};
}
violations[metric][dependency] = { limit, value };
}
});
});
return violations;
};
export const getViolations = (dependencies, totals, limit, overrides) => ({
collective: getCollectiveViolations(totals, limit),
individual: getIndividualViolations(dependencies, limit, overrides),
});