70 lines
2.7 KiB
JavaScript
70 lines
2.7 KiB
JavaScript
#!/usr/bin/env node
|
|
// For each npm package, prints its four newest major lines: first release,
|
|
// latest version and when that latest version was published. A line with no
|
|
// release for a long time has probably stopped receiving patches.
|
|
//
|
|
// Backs the version table in docs/GO-LIVE-PLAN.md §4. Re-run it before acting
|
|
// on that table — the numbers there are only true for the day they were taken.
|
|
//
|
|
// node scripts/check-majors.mjs # the packages the plan tracks
|
|
// node scripts/check-majors.mjs vite pinia # any packages
|
|
//
|
|
// Goes through the npm CLI rather than fetch() so the machine's registry or
|
|
// mirror settings (.npmrc) apply.
|
|
import { execSync } from 'node:child_process';
|
|
|
|
const TRACKED = [
|
|
'vue', 'vite', '@vitejs/plugin-vue', 'vite-plugin-pwa', 'vue-router', 'pinia',
|
|
'typescript', 'vue-tsc', 'tailwindcss', 'ant-design-vue', 'vant', '@vueuse/core',
|
|
'@nestjs/core', 'prisma',
|
|
];
|
|
// Package names only — they are interpolated into a shell command.
|
|
const PACKAGE_NAME = /^(@[a-z0-9][\w.-]*\/)?[a-z0-9][\w.-]*$/i;
|
|
const STALE_AFTER_DAYS = 180;
|
|
|
|
const pkgs = process.argv.length > 2 ? process.argv.slice(2) : TRACKED;
|
|
const now = Date.now();
|
|
|
|
for (const pkg of pkgs) {
|
|
if (!PACKAGE_NAME.test(pkg)) {
|
|
console.log(`\n${pkg}: not a package name, skipped`);
|
|
continue;
|
|
}
|
|
|
|
let published;
|
|
try {
|
|
published = JSON.parse(
|
|
execSync(`npm view ${pkg} time --json`, {
|
|
encoding: 'utf8',
|
|
timeout: 60_000,
|
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
}),
|
|
);
|
|
} catch {
|
|
console.log(`\n${pkg}: npm view failed`);
|
|
continue;
|
|
}
|
|
|
|
const lines = new Map();
|
|
for (const [version, date] of Object.entries(published)) {
|
|
// Stable releases only; this also drops the `created` / `modified` keys.
|
|
if (!/^\d+\.\d+\.\d+$/.test(version)) continue;
|
|
const major = Number(version.split('.')[0]);
|
|
const line = lines.get(major) ?? { firstVersion: version, first: date, lastVersion: version, last: date };
|
|
if (date < line.first) Object.assign(line, { firstVersion: version, first: date });
|
|
if (date > line.last) Object.assign(line, { lastVersion: version, last: date });
|
|
lines.set(major, line);
|
|
}
|
|
|
|
console.log(`\n${pkg}`);
|
|
const newestFirst = [...lines].sort(([a], [b]) => b - a).slice(0, 4);
|
|
for (const [major, line] of newestFirst) {
|
|
const idleDays = Math.floor((now - Date.parse(line.last)) / 86_400_000);
|
|
const stale = idleDays > STALE_AFTER_DAYS ? ` <- no release for ${idleDays} days` : '';
|
|
console.log(
|
|
` v${String(major).padEnd(3)} first ${line.firstVersion.padEnd(9)} ${line.first.slice(0, 10)}` +
|
|
` latest ${line.lastVersion.padEnd(9)} ${line.last.slice(0, 10)}${stale}`,
|
|
);
|
|
}
|
|
}
|