Skip to content

Commit 88567cc

Browse files
committed
Use release date of latest version instead of modified date
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.
1 parent e92cb9a commit 88567cc

File tree

1 file changed

+38
-16
lines changed

1 file changed

+38
-16
lines changed

src/ditched.ts

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#! /usr/bin/env node
1+
#!/usr/bin/env node
22
import path from "path";
33
import fs from "fs";
44
import https from "https";
@@ -49,15 +49,28 @@ function getJSON<T>(url: string): Promise<T> {
4949
});
5050
}
5151

52+
// A subset of the response returned by npm's registry
53+
type RegistryResponse = {
54+
"dist-tags": Record<string, string>;
55+
time: {
56+
created: string;
57+
modified: string;
58+
[version: string]: string;
59+
};
60+
};
61+
5262
type PackageInfo = {
5363
name: string;
54-
modifiedDate?: Date;
64+
mostRecentReleaseDate?: Date;
5565
};
5666

57-
function isDitched({ modifiedDate }: PackageInfo, ditchDays: number): boolean {
58-
if (!modifiedDate) return false;
67+
function isDitched(
68+
{ mostRecentReleaseDate }: PackageInfo,
69+
ditchDays: number
70+
): boolean {
71+
if (!mostRecentReleaseDate) return false;
5972
const ageDays =
60-
differenceInMilliseconds(new Date(), modifiedDate) / MS_IN_A_DAY;
73+
differenceInMilliseconds(new Date(), mostRecentReleaseDate) / MS_IN_A_DAY;
6174
return ageDays > ditchDays;
6275
}
6376

@@ -77,27 +90,30 @@ function printInfoTable(
7790
const table = new CliTable({
7891
head: [
7992
chalk.gray("Package"),
80-
chalk.gray("Last Modified"),
93+
chalk.gray("Latest Release"),
8194
chalk.gray("Ditched?"),
8295
],
8396
colWidths: [30, 40, 15],
8497
});
8598

8699
packagesToShow
87100
.sort((a, b) => {
88-
if (!a.modifiedDate) return -1;
89-
if (!b.modifiedDate) return 1;
90-
return differenceInMilliseconds(b.modifiedDate, a.modifiedDate);
101+
if (!a.mostRecentReleaseDate) return -1;
102+
if (!b.mostRecentReleaseDate) return 1;
103+
return differenceInMilliseconds(
104+
b.mostRecentReleaseDate,
105+
a.mostRecentReleaseDate
106+
);
91107
})
92108
.forEach((packageInfo) => {
93-
const { name, modifiedDate } = packageInfo;
109+
const { name, mostRecentReleaseDate } = packageInfo;
94110

95-
const formattedTime = modifiedDate
96-
? formatTimeSince(modifiedDate)
111+
const formattedTime = mostRecentReleaseDate
112+
? formatTimeSince(mostRecentReleaseDate)
97113
: "No package info found.";
98114

99115
let ditchedInfo = chalk.red("?");
100-
if (modifiedDate) {
116+
if (mostRecentReleaseDate) {
101117
ditchedInfo = isDitched(packageInfo, ditchDays)
102118
? chalk.red("Yes")
103119
: chalk.green("No");
@@ -112,12 +128,18 @@ function printInfoTable(
112128
async function getInfoForPackage(packageName: string): Promise<PackageInfo> {
113129
try {
114130
const regUrl = REGISTRY_URL + "/" + packageName;
115-
const response = await getJSON<{ time: { modified: string } }>(regUrl);
116-
const modifiedDate = new Date(response.time.modified);
131+
const response = await getJSON<RegistryResponse>(regUrl);
132+
133+
const mostRecentReleaseDate = new Date(
134+
Object.entries(response.time)
135+
.filter(([key]) => key !== "created" && key !== "modified")
136+
.map(([, value]) => value)
137+
.reduce((acc, el) => (el > acc ? el : acc))
138+
);
117139

118140
return {
119141
name: packageName,
120-
modifiedDate,
142+
mostRecentReleaseDate,
121143
};
122144
} catch (error) {
123145
return {

0 commit comments

Comments
 (0)