Skip to content

Commit

Permalink
fix(unpublish): Show warning on unpublish command when last version (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ebsaral authored and nlf committed Jan 6, 2022
1 parent 1f0d137 commit 2ac540b
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 3 deletions.
26 changes: 24 additions & 2 deletions lib/commands/unpublish.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,22 @@ const log = require('../utils/log-shim')
const otplease = require('../utils/otplease.js')
const getIdentity = require('../utils/get-identity.js')

const LAST_REMAINING_VERSION_ERROR = 'Refusing to delete the last version of the package. ' +
'It will block from republishing a new version for 24 hours.\n' +
'Run with --force to do this.'

const BaseCommand = require('../base-command.js')
class Unpublish extends BaseCommand {
static description = 'Remove a package from the registry'
static name = 'unpublish'
static params = ['dry-run', 'force', 'workspace', 'workspaces']
static usage = ['[<@scope>/]<pkg>[@<version>]']

async getKeysOfVersions (name, opts) {
const json = await npmFetch.json(npa(name).escapedName, opts)
return Object.keys(json.versions)
}

async completion (args) {
const { partialWord, conf } = args

Expand Down Expand Up @@ -44,8 +53,7 @@ class Unpublish extends BaseCommand {
return pkgs
}

const json = await npmFetch.json(npa(pkgs[0]).escapedName, opts)
const versions = Object.keys(json.versions)
const versions = await this.getKeysOfVersions(pkgs[0], opts)
if (!versions.length) {
return pkgs
} else {
Expand Down Expand Up @@ -97,12 +105,26 @@ class Unpublish extends BaseCommand {
const { name, version, publishConfig } = manifest
const pkgJsonSpec = npa.resolve(name, version)
const optsWithPub = { ...opts, publishConfig }

const versions = await this.getKeysOfVersions(name, optsWithPub)
if (versions.length === 1 && !force) {
throw this.usageError(
LAST_REMAINING_VERSION_ERROR
)
}

if (!dryRun) {
await otplease(opts, opts => libunpub(pkgJsonSpec, optsWithPub))
}
pkgName = name
pkgVersion = version ? `@${version}` : ''
} else {
const versions = await this.getKeysOfVersions(spec.name, opts)
if (versions.length === 1 && !force) {
throw this.usageError(
LAST_REMAINING_VERSION_ERROR
)
}
if (!dryRun) {
await otplease(opts, opts => libunpub(spec, opts))
}
Expand Down
48 changes: 47 additions & 1 deletion test/lib/commands/unpublish.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,23 @@ const { fake: mockNpm } = require('../../fixtures/mock-npm')

let result = ''
const noop = () => null
const versions = async () => {
return {
versions: {
'1.0.0': {},
'1.0.1': {},
},
}
}

const singleVersion = async () => {
return {
versions: {
'1.0.0': {},
},
}
}

const config = {
force: false,
loglevel: 'silly',
Expand All @@ -26,7 +43,7 @@ const npm = mockNpm({
const mocks = {
libnpmaccess: { lsPackages: noop },
libnpmpublish: { unpublish: noop },
'npm-registry-fetch': { json: noop },
'npm-registry-fetch': { json: versions },
'../../../lib/utils/otplease.js': async (opts, fn) => fn(opts),
'../../../lib/utils/get-identity.js': async () => 'foo',
'proc-log': { silly () {}, verbose () {} },
Expand Down Expand Up @@ -530,3 +547,32 @@ t.test('completion', async t => {
})
})
})

t.test('show error on unpublish <pkg>@version with package.json and the last version', async t => {
const Unpublish = t.mock('../../../lib/commands/unpublish.js', {
...mocks,
'npm-registry-fetch': { json: singleVersion },
path: { resolve: () => testDir, join: () => testDir + '/package.json' },
})
const unpublish = new Unpublish(npm)
await t.rejects(
unpublish.exec(['[email protected]']),
'Refusing to delete the last version of the package. ' +
'It will block from republishing a new version for 24 hours.\n' +
'Run with --force to do this.'
)
})

t.test('show error on unpublish <pkg>@version when the last version', async t => {
const Unpublish = t.mock('../../../lib/commands/unpublish.js', {
...mocks,
'npm-registry-fetch': { json: singleVersion },
})
const unpublish = new Unpublish(npm)
await t.rejects(
unpublish.exec(['[email protected]']),
'Refusing to delete the last version of the package. ' +
'It will block from republishing a new version for 24 hours.\n' +
'Run with --force to do this.'
)
})

0 comments on commit 2ac540b

Please sign in to comment.