Skip to content

Commit

Permalink
Merge pull request #84 from npm/latest
Browse files Browse the repository at this point in the history
Create a new pull request by comparing changes across two branches
  • Loading branch information
GulajavaMinistudio authored Dec 4, 2023
2 parents 7497e96 + f875caa commit fcdd5ca
Show file tree
Hide file tree
Showing 18 changed files with 599 additions and 501 deletions.
8 changes: 6 additions & 2 deletions docs/lib/content/commands/npm-unpublish.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ removing the tarball.
The npm registry will return an error if you are not [logged
in](/commands/npm-adduser).

If you do not specify a version or if you remove all of a package's
versions then the registry will remove the root package entry entirely.
If you do not specify a package name at all, the name and version to be
unpublished will be pulled from the project in the current directory.

If you specify a package name but do not specify a version or if you
remove all of a package's versions then the registry will remove the
root package entry entirely.

Even if you unpublish a package version, that specific name and version
combination can never be reused. In order to publish the package again,
Expand Down
109 changes: 61 additions & 48 deletions lib/commands/unpublish.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const libaccess = require('libnpmaccess')
const libunpub = require('libnpmpublish').unpublish
const npa = require('npm-package-arg')
const npmFetch = require('npm-registry-fetch')
const pacote = require('pacote')
const pkgJson = require('@npmcli/package-json')

const { flatten } = require('@npmcli/config/lib/definitions')
Expand All @@ -23,12 +23,12 @@ class Unpublish extends BaseCommand {
static ignoreImplicitWorkspace = false

static async getKeysOfVersions (name, opts) {
const pkgUri = npa(name).escapedName
const json = await npmFetch.json(`${pkgUri}?write=true`, {
const packument = await pacote.packument(name, {
...opts,
spec: name,
query: { write: true },
})
return Object.keys(json.versions)
return Object.keys(packument.versions)
}

static async completion (args, npm) {
Expand Down Expand Up @@ -59,28 +59,43 @@ class Unpublish extends BaseCommand {
return pkgs
}

const versions = await this.getKeysOfVersions(pkgs[0], opts)
const versions = await Unpublish.getKeysOfVersions(pkgs[0], opts)
if (!versions.length) {
return pkgs
} else {
return versions.map(v => `${pkgs[0]}@${v}`)
}
}

async exec (args) {
async exec (args, { localPrefix } = {}) {
if (args.length > 1) {
throw this.usageError()
}

let spec = args.length && npa(args[0])
// workspace mode
if (!localPrefix) {
localPrefix = this.npm.localPrefix
}

const force = this.npm.config.get('force')
const { silent } = this.npm
const dryRun = this.npm.config.get('dry-run')

let spec
if (args.length) {
spec = npa(args[0])
if (spec.type !== 'version' && spec.rawSpec !== '*') {
throw this.usageError(
'Can only unpublish a single version, or the entire project.\n' +
'Tags and ranges are not supported.'
)
}
}

log.silly('unpublish', 'args[0]', args[0])
log.silly('unpublish', 'spec', spec)

if ((!spec || !spec.rawSpec) && !force) {
if (spec?.rawSpec === '*' && !force) {
throw this.usageError(
'Refusing to delete entire project.\n' +
'Run with --force to do this.'
Expand All @@ -89,69 +104,67 @@ class Unpublish extends BaseCommand {

const opts = { ...this.npm.flatOptions }

let pkgName
let pkgVersion
let manifest
let manifestErr
try {
const { content } = await pkgJson.prepare(this.npm.localPrefix)
const { content } = await pkgJson.prepare(localPrefix)
manifest = content
} catch (err) {
manifestErr = err
}
if (spec) {
// If cwd has a package.json with a name that matches the package being
// unpublished, load up the publishConfig
if (manifest && manifest.name === spec.name && manifest.publishConfig) {
flatten(manifest.publishConfig, opts)
}
const versions = await Unpublish.getKeysOfVersions(spec.name, opts)
if (versions.length === 1 && !force) {
throw this.usageError(LAST_REMAINING_VERSION_ERROR)
}
pkgName = spec.name
pkgVersion = spec.type === 'version' ? `@${spec.rawSpec}` : ''
} else {
if (manifestErr) {
if (manifestErr.code === 'ENOENT' || manifestErr.code === 'ENOTDIR') {
if (err.code === 'ENOENT' || err.code === 'ENOTDIR') {
if (!spec) {
// We needed a local package.json to figure out what package to
// unpublish
throw this.usageError()
} else {
throw manifestErr
}
} else {
// folks should know if ANY local package.json had a parsing error.
// They may be relying on `publishConfig` to be loading and we don't
// want to ignore errors in that case.
throw err
}
}

log.verbose('unpublish', manifest)

let pkgVersion // for cli output
if (spec) {
pkgVersion = spec.type === 'version' ? `@${spec.rawSpec}` : ''
} else {
spec = npa.resolve(manifest.name, manifest.version)
if (manifest.publishConfig) {
flatten(manifest.publishConfig, opts)
log.verbose('unpublish', manifest)
pkgVersion = manifest.version ? `@${manifest.version}` : ''
if (!manifest.version && !force) {
throw this.usageError(
'Refusing to delete entire project.\n' +
'Run with --force to do this.'
)
}
}

pkgName = manifest.name
pkgVersion = manifest.version ? `@${manifest.version}` : ''
// If localPrefix has a package.json with a name that matches the package
// being unpublished, load up the publishConfig
if (manifest?.name === spec.name && manifest.publishConfig) {
flatten(manifest.publishConfig, opts)
}

const versions = await Unpublish.getKeysOfVersions(spec.name, opts)
if (versions.length === 1 && spec.rawSpec === versions[0] && !force) {
throw this.usageError(LAST_REMAINING_VERSION_ERROR)
}
if (versions.length === 1) {
pkgVersion = ''
}

if (!dryRun) {
await otplease(this.npm, opts, o => libunpub(spec, o))
}
if (!silent) {
this.npm.output(`- ${pkgName}${pkgVersion}`)
this.npm.output(`- ${spec.name}${pkgVersion}`)
}
}

async execWorkspaces (args) {
await this.setWorkspaces()

const force = this.npm.config.get('force')
if (!force) {
throw this.usageError(
'Refusing to delete entire project(s).\n' +
'Run with --force to do this.'
)
}

for (const name of this.workspaceNames) {
await this.exec([name])
for (const path of this.workspacePaths) {
await this.exec(args, { localPrefix: path })
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions lib/utils/sbom-spdx.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ const SPDX_IDENTIFER = 'SPDXRef-DOCUMENT'
const NO_ASSERTION = 'NOASSERTION'

const REL_DESCRIBES = 'DESCRIBES'
const REL_PREREQ = 'HAS_PREREQUISITE'
const REL_PREREQ = 'PREREQUISITE_FOR'
const REL_OPTIONAL = 'OPTIONAL_DEPENDENCY_OF'
const REL_DEV = 'DEV_DEPENDENCY_OF'
const REL_DEP = 'DEPENDS_ON'
const REL_DEP = 'DEPENDENCY_OF'

const REF_CAT_PACKAGE_MANAGER = 'PACKAGE-MANAGER'
const REF_TYPE_PURL = 'purl'
Expand Down Expand Up @@ -147,8 +147,8 @@ const toSpdxRelationship = (node, edge) => {
}

return {
spdxElementId: toSpdxID(node),
relatedSpdxElement: toSpdxID(edge.to),
spdxElementId: toSpdxID(edge.to),
relatedSpdxElement: toSpdxID(node),
relationshipType: type,
}
}
Expand Down
28 changes: 14 additions & 14 deletions tap-snapshots/test/lib/commands/pack.js.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ Array [
name: test-package
version: 1.0.0
filename: test-package-1.0.0.tgz
package size: 136 B
package size: {size}
unpacked size: 41 B
shasum: a92a0679a70a450f14f98a468756948a679e4107
integrity: sha512-Gka9ZV/Bryxky[...]LgMJ+0F+FhXMA==
shasum: {sha}
integrity: {integrity}
total files: 1
),
"",
Expand All @@ -41,14 +41,14 @@ Array [
Object {
"mode": 420,
"path": "package.json",
"size": 41,
"size": "{size}",
},
],
"id": "test-package@1.0.0",
"integrity": "sha512-Gka9ZV/BryxkypfvMpTvLfaJE1AUi7PK1EAbYqnVzqtucf6QvUK4CFsLVzagY1GwZVx2T1jwWLgMJ+0F+FhXMA==",
"integrity": "{integrity}",
"name": "test-package",
"shasum": "a92a0679a70a450f14f98a468756948a679e4107",
"size": 136,
"shasum": "{sha}",
"size": "{size}",
"unpackedSize": 41,
"version": "1.0.0",
},
Expand All @@ -71,14 +71,14 @@ Array [
Object {
"mode": 420,
"path": "package.json",
"size": 50,
"size": "{size}",
},
],
"id": "@myscope/test-package@1.0.0",
"integrity": "sha512-bUu8iTm2E5DZMrwKeyx963K6ViEmaFocXh75EujgI+FHSaJeqvObcdk1KFwdx8CbOgsfNHEvWNQw/bONAJsoNw==",
"integrity": "{integrity}",
"name": "@myscope/test-package",
"shasum": "7e6eb2e1ca46bed6b8fa8e144e0fcd1b22fe2d98",
"size": 145,
"shasum": "{sha}",
"size": "{size}",
"unpackedSize": 50,
"version": "1.0.0",
},
Expand All @@ -97,10 +97,10 @@ Array [
name: test-package
version: 1.0.0
filename: test-package-1.0.0.tgz
package size: 136 B
package size: {size}
unpacked size: 41 B
shasum: a92a0679a70a450f14f98a468756948a679e4107
integrity: sha512-Gka9ZV/Bryxky[...]LgMJ+0F+FhXMA==
shasum: {sha}
integrity: {integrity}
total files: 1
),
"",
Expand Down
Loading

0 comments on commit fcdd5ca

Please sign in to comment.