Skip to content

Commit

Permalink
Use release date of latest version instead of modified date
Browse files Browse the repository at this point in the history
The `time.modified` field is apparently not the time of the latest
release, it can be much more recent. I have not found any good
documentation on exactly what "modified" means.

I think using the most recent release date is the best measure for
detecting if a package is ditched or not. Note that this does not mean
the version tagged with the "latest" tag - this will also consider other
tags, like rc, alpha, next, etc.
  • Loading branch information
draperunner committed Jun 1, 2022
1 parent e92cb9a commit 88567cc
Showing 1 changed file with 38 additions and 16 deletions.
54 changes: 38 additions & 16 deletions src/ditched.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#! /usr/bin/env node
#!/usr/bin/env node
import path from "path";
import fs from "fs";
import https from "https";
Expand Down Expand Up @@ -49,15 +49,28 @@ function getJSON<T>(url: string): Promise<T> {
});
}

// A subset of the response returned by npm's registry
type RegistryResponse = {
"dist-tags": Record<string, string>;
time: {
created: string;
modified: string;
[version: string]: string;
};
};

type PackageInfo = {
name: string;
modifiedDate?: Date;
mostRecentReleaseDate?: Date;
};

function isDitched({ modifiedDate }: PackageInfo, ditchDays: number): boolean {
if (!modifiedDate) return false;
function isDitched(
{ mostRecentReleaseDate }: PackageInfo,
ditchDays: number
): boolean {
if (!mostRecentReleaseDate) return false;
const ageDays =
differenceInMilliseconds(new Date(), modifiedDate) / MS_IN_A_DAY;
differenceInMilliseconds(new Date(), mostRecentReleaseDate) / MS_IN_A_DAY;
return ageDays > ditchDays;
}

Expand All @@ -77,27 +90,30 @@ function printInfoTable(
const table = new CliTable({
head: [
chalk.gray("Package"),
chalk.gray("Last Modified"),
chalk.gray("Latest Release"),
chalk.gray("Ditched?"),
],
colWidths: [30, 40, 15],
});

packagesToShow
.sort((a, b) => {
if (!a.modifiedDate) return -1;
if (!b.modifiedDate) return 1;
return differenceInMilliseconds(b.modifiedDate, a.modifiedDate);
if (!a.mostRecentReleaseDate) return -1;
if (!b.mostRecentReleaseDate) return 1;
return differenceInMilliseconds(
b.mostRecentReleaseDate,
a.mostRecentReleaseDate
);
})
.forEach((packageInfo) => {
const { name, modifiedDate } = packageInfo;
const { name, mostRecentReleaseDate } = packageInfo;

const formattedTime = modifiedDate
? formatTimeSince(modifiedDate)
const formattedTime = mostRecentReleaseDate
? formatTimeSince(mostRecentReleaseDate)
: "No package info found.";

let ditchedInfo = chalk.red("?");
if (modifiedDate) {
if (mostRecentReleaseDate) {
ditchedInfo = isDitched(packageInfo, ditchDays)
? chalk.red("Yes")
: chalk.green("No");
Expand All @@ -112,12 +128,18 @@ function printInfoTable(
async function getInfoForPackage(packageName: string): Promise<PackageInfo> {
try {
const regUrl = REGISTRY_URL + "/" + packageName;
const response = await getJSON<{ time: { modified: string } }>(regUrl);
const modifiedDate = new Date(response.time.modified);
const response = await getJSON<RegistryResponse>(regUrl);

const mostRecentReleaseDate = new Date(
Object.entries(response.time)
.filter(([key]) => key !== "created" && key !== "modified")
.map(([, value]) => value)
.reduce((acc, el) => (el > acc ? el : acc))
);

return {
name: packageName,
modifiedDate,
mostRecentReleaseDate,
};
} catch (error) {
return {
Expand Down

0 comments on commit 88567cc

Please sign in to comment.