mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-23 23:29:17 -05:00
feat: improve error message for versions not meeting minimumReleaseAge (#10350)
close #10307
This commit is contained in:
7
.changeset/clear-minimum-release-age-error.md
Normal file
7
.changeset/clear-minimum-release-age-error.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@pnpm/npm-resolver": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
Improve error message when a package version exists but does not meet the `minimumReleaseAge` constraint. The error now clearly states that the version exists and shows a human-readable time since release (e.g., "released 6 hours ago") [#10307](https://github.com/pnpm/pnpm/issues/10307).
|
||||
|
||||
@@ -398,5 +398,5 @@ test('dlx should fail when the requested package does not meet the minimum age r
|
||||
default: 'https://registry.npmjs.org/',
|
||||
},
|
||||
}, ['shx@0.3.4'])
|
||||
).rejects.toThrow('No matching version found for shx@0.3.4 published by')
|
||||
).rejects.toThrow(/Version 0\.3\.4 \(released .+\) of shx does not meet the minimumReleaseAge constraint/)
|
||||
})
|
||||
|
||||
@@ -412,7 +412,7 @@ test('minimumReleaseAge makes install fail if there is no version that was publi
|
||||
dir: path.resolve('project'),
|
||||
minimumReleaseAge,
|
||||
linkWorkspacePackages: false,
|
||||
}, ['is-odd@0.1.1'])).rejects.toThrow(/No matching version found for is-odd@0\.1\.1.*satisfies the specs but/)
|
||||
}, ['is-odd@0.1.1'])).rejects.toThrow(/Version 0\.1\.1 \(released .+\) of is-odd does not meet the minimumReleaseAge constraint/)
|
||||
})
|
||||
|
||||
describeOnLinuxOnly('filters optional dependencies based on pnpm.supportedArchitectures.libc', () => {
|
||||
|
||||
@@ -70,7 +70,9 @@ export class NoMatchingVersionError extends PnpmError {
|
||||
let errorMessage: string
|
||||
if (opts.publishedBy && opts.immatureVersion && opts.packageMeta.time) {
|
||||
const time = new Date(opts.packageMeta.time[opts.immatureVersion])
|
||||
errorMessage = `No matching version found for ${dep} published by ${opts.publishedBy.toString()} while fetching it from ${opts.registry}. Version ${opts.immatureVersion} satisfies the specs but was released at ${time.toString()}`
|
||||
const releaseAgeText = formatTimeAgo(time)
|
||||
const pkgName = opts.wantedDependency.alias ?? opts.packageMeta.name
|
||||
errorMessage = `Version ${opts.immatureVersion} (released ${releaseAgeText}) of ${pkgName} does not meet the minimumReleaseAge constraint`
|
||||
} else {
|
||||
errorMessage = `No matching version found for ${dep} while fetching it from ${opts.registry}`
|
||||
}
|
||||
@@ -80,6 +82,28 @@ export class NoMatchingVersionError extends PnpmError {
|
||||
}
|
||||
}
|
||||
|
||||
function formatTimeAgo (date: Date): string {
|
||||
const now = Date.now()
|
||||
const diffMs = now - date.getTime()
|
||||
|
||||
// Handle clock skew (future dates) and very recent releases (< 1 minute)
|
||||
if (diffMs < 60 * 1000) {
|
||||
return 'just now'
|
||||
}
|
||||
|
||||
const diffMinutes = Math.floor(diffMs / (60 * 1000))
|
||||
const diffHours = Math.floor(diffMs / (60 * 60 * 1000))
|
||||
const diffDays = Math.floor(diffMs / (24 * 60 * 60 * 1000))
|
||||
|
||||
if (diffHours >= 48) {
|
||||
return `${diffDays} day${diffDays === 1 ? '' : 's'} ago`
|
||||
}
|
||||
if (diffMinutes >= 90) {
|
||||
return `${diffHours} hour${diffHours === 1 ? '' : 's'} ago`
|
||||
}
|
||||
return `${diffMinutes} minute${diffMinutes === 1 ? '' : 's'} ago`
|
||||
}
|
||||
|
||||
export {
|
||||
parseBareSpecifier,
|
||||
workspacePrefToNpm,
|
||||
|
||||
@@ -116,7 +116,7 @@ test('do not pick version that does not satisfy the date requirement even if it
|
||||
})
|
||||
await expect(resolveFromNpm({ alias: 'foo', bareSpecifier: '1.0.0' }, {
|
||||
publishedBy: new Date('2015-08-17T19:26:00.508Z'),
|
||||
})).rejects.toThrow('No matching version found')
|
||||
})).rejects.toThrow(/Version 1\.0\.0 \(released .+\) of foo does not meet the minimumReleaseAge constraint/)
|
||||
})
|
||||
|
||||
test('should skip time field validation for excluded packages', async () => {
|
||||
|
||||
Reference in New Issue
Block a user