Skip to content

Commit 8f92e74

Browse files
authored
fix(unpublish): refuse to unpublish a version when registry has no versions (#10117)
1 parent dc95d49 commit 8f92e74

2 files changed

Lines changed: 47 additions & 1 deletion

File tree

‎lib/commands/unpublish.js‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class Unpublish extends BaseCommand {
2626
query: { write: true },
2727
_isRoot: true,
2828
})
29-
return Object.keys(packument.versions)
29+
return Object.keys(packument.versions || {})
3030
}
3131

3232
static async completion (args, npm) {
@@ -136,6 +136,9 @@ class Unpublish extends BaseCommand {
136136
}
137137

138138
const versions = await Unpublish.getKeysOfVersions(spec.name, opts)
139+
if (versions.length === 0 && spec.type === 'version') {
140+
throw this.usageError(`Refusing to delete ${spec.name}@${spec.rawSpec}: the registry returned no versions for ${spec.name}.`)
141+
}
139142
if (versions.length === 1 && spec.rawSpec === versions[0] && !force) {
140143
throw this.usageError(LAST_REMAINING_VERSION_ERROR)
141144
}

‎test/lib/commands/unpublish.js‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,49 @@ t.test('unpublish <pkg>@version last version', async t => {
166166
)
167167
})
168168

169+
t.test('unpublish <pkg>@version of a packument with no versions', async t => {
170+
const { npm } = await loadMockNpm(t, {
171+
config: {
172+
...auth,
173+
},
174+
})
175+
const registry = new MockRegistry({
176+
tap: t,
177+
registry: npm.config.get('registry'),
178+
authorization: 'test-auth-token',
179+
})
180+
const manifest = registry.manifest({ name: pkg })
181+
delete manifest.versions
182+
await registry.package({ manifest, query: { write: true } })
183+
184+
await t.rejects(
185+
npm.exec('unpublish', ['test-package@1.0.0']),
186+
/the registry returned no versions for test-package/
187+
)
188+
})
189+
190+
t.test('unpublish <pkg>@version of a packument with no versions with --force', async t => {
191+
const { npm } = await loadMockNpm(t, {
192+
config: {
193+
force: true,
194+
...auth,
195+
},
196+
})
197+
const registry = new MockRegistry({
198+
tap: t,
199+
registry: npm.config.get('registry'),
200+
authorization: 'test-auth-token',
201+
})
202+
const manifest = registry.manifest({ name: pkg })
203+
manifest.versions = {}
204+
await registry.package({ manifest, query: { write: true } })
205+
206+
await t.rejects(
207+
npm.exec('unpublish', ['test-package@1.0.0']),
208+
/the registry returned no versions for test-package/
209+
)
210+
})
211+
169212
t.test('no version found in package.json no force', async t => {
170213
const { npm } = await loadMockNpm(t, {
171214
config: {

0 commit comments

Comments
 (0)