Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions lib/commands/pack.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ const pacote = require('pacote')
const libpack = require('libnpmpack')
const npa = require('npm-package-arg')
const { log, output } = require('proc-log')
const {
isReleaseAgeExcluded,
trustedSpecName,
} = require('@npmcli/arborist/lib/release-age-exclude.js')
const { getContents, logTar } = require('../utils/tar.js')
const BaseCommand = require('../base-cmd.js')

Expand Down Expand Up @@ -35,23 +39,27 @@ class Pack extends BaseCommand {
const manifests = []
for (const arg of args) {
const spec = npa(arg)
const options = isReleaseAgeExcluded(
trustedSpecName(spec),
this.npm.flatOptions.minReleaseAgeExclude
) ? { ...this.npm.flatOptions, before: null } : this.npm.flatOptions
const manifest = await pacote.manifest(spec, {
...this.npm.flatOptions,
...options,
Arborist,
preferOnline: true,
_isRoot: true,
})
if (!manifest._id) {
throw new Error('Invalid package, must have name and version')
}
manifests.push({ arg, manifest })
manifests.push({ arg, manifest, options })
}

// Load tarball names up for printing afterward to isolate from the noise generated during packing
const tarballs = []
for (const { arg, manifest } of manifests) {
for (const { arg, manifest, options } of manifests) {
const tarballData = await libpack(arg, {
...this.npm.flatOptions,
...options,
foregroundScripts: this.npm.config.isDefault('foreground-scripts')
? true
: this.npm.config.get('foreground-scripts'),
Expand Down
56 changes: 56 additions & 0 deletions test/lib/commands/pack.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const t = require('tap')
const { load: loadMockNpm } = require('../../fixtures/mock-npm')
const { cleanZlib } = require('../../fixtures/clean-snapshot')
const MockRegistry = require('@npmcli/mock-registry')
const path = require('node:path')
const fs = require('node:fs')

Expand Down Expand Up @@ -162,6 +163,61 @@ t.test('foreground-scripts can still be set to false', async t => {
t.throws(() => fs.statSync(path.resolve(npm.prefix, filename)))
})

t.test('min-release-age-exclude applies to registry packages', async t => {
const name = '@myscope/some-package'
const version = '1.2.3'
const { npm, outputs } = await loadMockNpm(t, {
prefixDir: {
package: {
'package.json': JSON.stringify({ name, version }),
},
},
config: {
'min-release-age': 7,
'min-release-age-exclude': ['@myscope/*'],
},
})
const registry = new MockRegistry({
tap: t,
registry: npm.config.get('registry'),
})
const manifest = registry.manifest({ name, versions: [version] })
await registry.package({
manifest,
times: 2,
tarballs: { [version]: path.join(npm.prefix, 'package') },
})

await npm.exec('pack', [`${name}@${version}`])

const filename = 'myscope-some-package-1.2.3.tgz'
t.strictSame(outputs, [filename])
t.ok(fs.statSync(path.resolve(npm.prefix, filename)))
})

t.test('excluded alias name does not bypass min-release-age for its target', async t => {
const target = 'other-package'
const version = '1.2.3'
const { npm } = await loadMockNpm(t, {
config: {
'min-release-age': 7,
'min-release-age-exclude': ['@myscope/*'],
},
})
const registry = new MockRegistry({
tap: t,
registry: npm.config.get('registry'),
})
await registry.package({
manifest: registry.manifest({ name: target, versions: [version] }),
})

await t.rejects(
npm.exec('pack', [`@myscope/alias@npm:${target}@${version}`]),
{ code: 'ETARGET' }
)
})

t.test('invalid packument', async t => {
const { npm, outputs } = await loadMockNpm(t, {
prefixDir: {
Expand Down
Loading