pkg-stats
Version:
Beautiful NPM package download stats
88 lines (87 loc) • 3.12 kB
JavaScript
import { versionCompare } from './version.js';
export function groupStats(stats, type) {
if (type === 'major') {
return { type: 'major', stats: groupByMajor(stats) };
}
if (type === 'minor') {
return { type: 'minor', stats: groupByMinor(stats) };
}
if (type === 'patch') {
return { type: 'patch', stats: groupByPatch(stats) };
}
const groupedByMajor = groupByMajor(stats);
if (groupedByMajor.length >= 3) {
return { type: 'major', stats: groupedByMajor };
}
const groupedByMinor = groupByMinor(stats);
if (groupedByMinor.length >= 3) {
return { type: 'minor', stats: groupedByMinor };
}
return { type: 'patch', stats: groupByPatch(stats) };
}
function groupByMajor(stats) {
const result = {};
for (const versionStats of stats) {
const key = `${versionStats.major}.x`;
const entry = result[key] ?? {
version: { major: versionStats.major },
versionString: key,
downloads: 0,
};
result[key] = entry;
entry.downloads += versionStats.downloads;
}
return Object.values(result).sort((a, b) => versionCompare(a.version, b.version));
}
function groupByMinor(stats) {
const result = {};
for (const versionStats of stats) {
const key = `${versionStats.major}.${versionStats.minor}.x`;
const entry = result[key] ?? {
version: { major: versionStats.major, minor: versionStats.minor },
versionString: key,
downloads: 0,
};
result[key] = entry;
entry.downloads += versionStats.downloads;
}
return Object.values(result).sort((a, b) => versionCompare(a.version, b.version));
}
function groupByPatch(stats) {
const result = {};
for (const versionStats of stats) {
const key = `${versionStats.major}.${versionStats.minor}.${versionStats.patch}`;
const entry = result[key] ?? {
version: {
major: versionStats.major,
minor: versionStats.minor,
patch: versionStats.patch,
},
versionString: key,
downloads: 0,
};
result[key] = entry;
entry.downloads += versionStats.downloads;
}
return Object.values(result).sort((a, b) => versionCompare(a.version, b.version));
}
export function filterStats(stats, options) {
if (options.all) {
return stats;
}
if (options.top) {
return pickTopStats(stats, options.top);
}
const downloadThreshold = 0.005 * options.totalDownloads; // 0.5%
const filtered = stats.filter((stat) => stat.downloads >= downloadThreshold);
// If we were to skip only a single state, we rather display it than replace it with "rest".
if (filtered.length + 1 >= stats.length) {
return stats;
}
return filtered;
}
function pickTopStats(stats, top) {
const sortedStats = stats.sort((a, b) => b.downloads - a.downloads);
const topStats = sortedStats.slice(0, top);
return topStats.sort((a, b) => versionCompare(a.version, b.version));
}