Skip to content

Commit 1622ac4

Browse files
committed
fix: handle missing time in packument to prevent crash on npm view
1 parent ed1a28e commit 1622ac4

File tree

3 files changed

+51
-4
lines changed

3 files changed

+51
-4
lines changed

lib/commands/view.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -266,11 +266,13 @@ class View extends BaseCommand {
266266
const deps = Object.entries(manifest.dependencies || {}).map(([k, dep]) =>
267267
`${chalk.blue(k)}: ${dep}`
268268
)
269-
// Sort dist-tags by publish time, then tag name, keeping latest at the top of the list
269+
270+
// Sort dist-tags by publish time when available, then by tag name, keeping `latest` at the top of the list.
270271
const distTags = Object.entries(packu['dist-tags'])
271272
.sort(([aTag, aVer], [bTag, bVer]) => {
272-
const aTime = aTag === 'latest' ? Infinity : Date.parse(packu.time[aVer])
273-
const bTime = bTag === 'latest' ? Infinity : Date.parse(packu.time[bVer])
273+
const timeMap = packu.time || {}
274+
const aTime = aTag === 'latest' ? Infinity : Date.parse(timeMap[aVer] || 0)
275+
const bTime = bTag === 'latest' ? Infinity : Date.parse(timeMap[bVer] || 0)
274276
if (aTime === bTime) {
275277
return aTag > bTag ? -1 : 1
276278
}
@@ -357,7 +359,7 @@ class View extends BaseCommand {
357359
})
358360
if (publisher || packu.time) {
359361
let publishInfo = 'published'
360-
if (packu.time) {
362+
if (packu.time?.[manifest.version]) {
361363
publishInfo += ` ${chalk.cyan(relativeDate(packu.time[manifest.version]))}`
362364
}
363365
if (publisher) {

tap-snapshots/test/lib/commands/view.js.test.cjs

+16
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,22 @@ dist-tags:
279279
latest: 1.0.0
280280
`
281281

282+
exports[`test/lib/commands/view.js TAP package with multiple dist‑tags and no time > must match snapshot 1`] = `
283+
284+
[[email protected] | Proprietary | deps: none | versions: 1
285+
286+
dist
287+
.tarball: http://gray/1.1.0.tgz
288+
.shasum: b
289+
290+
dist-tags:
291+
latest: 1.1.0
292+
stable: 1.1.0
293+
old: 1.0.0
294+
beta: 1.2.0-beta
295+
alpha: 1.2.0-alpha
296+
`
297+
282298
exports[`test/lib/commands/view.js TAP package with no modified time > must match snapshot 1`] = `
283299
284300
[[email protected] | Proprietary | deps: none | versions: 2

test/lib/commands/view.js

+29
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,29 @@ const packument = (nv, opts) => {
7979
},
8080
},
8181
},
82+
// package with no time attribute
83+
gray: {
84+
_id: 'gray',
85+
name: 'gray',
86+
'dist-tags': {
87+
latest: '1.1.0',
88+
beta: '1.2.0-beta',
89+
alpha: '1.2.0-alpha',
90+
old: '1.0.0',
91+
stable: '1.1.0',
92+
},
93+
versions: {
94+
'1.1.0': {
95+
name: 'gray',
96+
version: '1.1.0',
97+
dist: {
98+
shasum: 'b',
99+
tarball: 'http://gray/1.1.0.tgz',
100+
fileCount: 1,
101+
},
102+
},
103+
},
104+
},
82105
cyan: {
83106
_npmUser: {
84107
name: 'claudia',
@@ -769,3 +792,9 @@ t.test('no package completion', async t => {
769792
t.notOk(res, 'there is no package completion')
770793
t.end()
771794
})
795+
796+
t.test('package with multiple dist‑tags and no time', async t => {
797+
const { view, joinedOutput } = await loadMockNpm(t, { config: { unicode: false } })
798+
await view.exec(['https://github.com/npm/gray'])
799+
t.matchSnapshot(joinedOutput())
800+
})

0 commit comments

Comments
 (0)