diff --git a/scripts/check-package-age.js b/scripts/check-package-age.js index ef1b9c1..8326438 100755 --- a/scripts/check-package-age.js +++ b/scripts/check-package-age.js @@ -14,33 +14,77 @@ const TWO_WEEKS_MS = 14 * 24 * 60 * 60 * 1000; function getPackageInfo(packageName, version) { return new Promise((resolve, reject) => { // Remove version prefixes like ^, ~, >= - const cleanVersion = version.replace(/^[\^~>=]+/, ''); + let cleanVersion = version.replace(/^[\^~>=]+/, ''); - const url = `https://registry.npmjs.org/${packageName}/${cleanVersion}`; + // If version contains .x or wildcards, fetch all versions and find latest matching + if (cleanVersion.includes('x') || cleanVersion.includes('*')) { + const url = `https://registry.npmjs.org/${packageName}`; - https.get(url, (res) => { - let data = ''; + https.get(url, (res) => { + let data = ''; - res.on('data', (chunk) => { - data += chunk; + res.on('data', (chunk) => { + data += chunk; + }); + + res.on('end', () => { + try { + const info = JSON.parse(data); + const versions = Object.keys(info.versions || {}); + + // Convert version pattern to regex (e.g., "19.2.x" -> /^19\.2\.\d+$/) + const pattern = cleanVersion.replace(/\./g, '\\.').replace(/x|\*/g, '\\d+'); + const regex = new RegExp(`^${pattern}$`); + + // Find matching versions and get the latest + const matchingVersions = versions.filter(v => regex.test(v)).sort(); + const latestMatching = matchingVersions[matchingVersions.length - 1]; + + if (latestMatching && info.time && info.time[latestMatching]) { + resolve({ + name: packageName, + version: latestMatching, + published: info.time[latestMatching], + error: null + }); + } else { + reject(new Error(`No matching version found for ${packageName}@${cleanVersion}`)); + } + } catch (err) { + reject(new Error(`Failed to parse response for ${packageName}@${cleanVersion}`)); + } + }); + }).on('error', (err) => { + reject(err); }); + } else { + // Exact version lookup + const url = `https://registry.npmjs.org/${packageName}/${cleanVersion}`; - res.on('end', () => { - try { - const info = JSON.parse(data); - resolve({ - name: packageName, - version: cleanVersion, - published: info.time || info._time, - error: null - }); - } catch (err) { - reject(new Error(`Failed to parse response for ${packageName}@${cleanVersion}`)); - } + https.get(url, (res) => { + let data = ''; + + res.on('data', (chunk) => { + data += chunk; + }); + + res.on('end', () => { + try { + const info = JSON.parse(data); + resolve({ + name: packageName, + version: cleanVersion, + published: info.time || info._time, + error: null + }); + } catch (err) { + reject(new Error(`Failed to parse response for ${packageName}@${cleanVersion}`)); + } + }); + }).on('error', (err) => { + reject(err); }); - }).on('error', (err) => { - reject(err); - }); + } }); }