Skip to content

Commit ffbdea2

Browse files
authored
fix: npm pack filename on scoped packages (#5894)
When running `npm pack` on a scoped package, the file name would be incorrect, since the `@` character should be removed, and the `/` character be replaced with a `-` character
1 parent 40f2c21 commit ffbdea2

File tree

6 files changed

+115
-3
lines changed

6 files changed

+115
-3
lines changed

lib/utils/tar.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,9 @@ const getContents = async (manifest, tarball) => {
120120
unpackedSize: totalEntrySize,
121121
shasum,
122122
integrity: ssri.parse(integrity.sha512[0]),
123-
filename: `${manifest.name}-${manifest.version}.tgz`,
123+
// @scope/packagename.tgz => scope-packagename.tgz
124+
// we can safely use these global replace rules due to npm package naming rules
125+
filename: `${manifest.name.replace('@', '').replace('/', '-')}-${manifest.version}.tgz`,
124126
files: uppers.concat(others),
125127
entryCount: totalEntries,
126128
bundled: Array.from(bundled),

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

+30
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,36 @@ Array [
5656
]
5757
`
5858

59+
exports[`test/lib/commands/pack.js TAP should log scoped package output as valid json > logs pack contents 1`] = `
60+
Array []
61+
`
62+
63+
exports[`test/lib/commands/pack.js TAP should log scoped package output as valid json > outputs as json 1`] = `
64+
Array [
65+
Array [
66+
Object {
67+
"bundled": Array [],
68+
"entryCount": 1,
69+
"filename": "myscope-test-package-1.0.0.tgz",
70+
"files": Array [
71+
Object {
72+
"mode": 420,
73+
"path": "package.json",
74+
"size": 50,
75+
},
76+
],
77+
"id": "@myscope/test-package@1.0.0",
78+
"integrity": "sha512-bUu8iTm2E5DZMrwKeyx963K6ViEmaFocXh75EujgI+FHSaJeqvObcdk1KFwdx8CbOgsfNHEvWNQw/bONAJsoNw==",
79+
"name": "@myscope/test-package",
80+
"shasum": "7e6eb2e1ca46bed6b8fa8e144e0fcd1b22fe2d98",
81+
"size": 145,
82+
"unpackedSize": 50,
83+
"version": "1.0.0",
84+
},
85+
],
86+
]
87+
`
88+
5989
exports[`test/lib/commands/pack.js TAP should pack current directory with no arguments > logs pack contents 1`] = `
6090
Array [
6191
undefined,

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ Array [
136136
String(
137137
name: @npm/test-package
138138
version: 1.0.0
139-
filename: @npm/test-package-1.0.0.tgz
139+
filename: npm-test-package-1.0.0.tgz
140140
package size: 147 B
141141
unpacked size: 55 B
142142
shasum:{sha}
@@ -191,7 +191,7 @@ Array [
191191
String(
192192
name: @npm/test-package
193193
version: 1.0.0
194-
filename: @npm/test-package-1.0.0.tgz
194+
filename: npm-test-package-1.0.0.tgz
195195
package size: 147 B
196196
unpacked size: 55 B
197197
shasum:{sha}

tap-snapshots/test/lib/utils/tar.js.test.cjs

+30
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,34 @@ own files: 5
3333
total files: 5
3434
3535
36+
`
37+
38+
exports[`test/lib/utils/tar.js TAP should log tarball contents of a scoped package > must match snapshot 1`] = `
39+
40+
41+
package: @myscope/my-cool-pkg@1.0.0
42+
=== Tarball Contents ===
43+
44+
4B cat
45+
4B chai
46+
4B dog
47+
123B package.json
48+
=== Bundled Dependencies ===
49+
50+
bundle-dep
51+
=== Tarball Details ===
52+
53+
name: @myscope/my-cool-pkg
54+
version: 1.0.0
55+
filename: myscope-my-cool-pkg-1.0.0.tgz
56+
package size: 280 B
57+
unpacked size: 135 B
58+
shasum: a4f63307f2211e8fde72cd39bc1176b4fe997b71
59+
integrity: sha512-b+RavF8JiErJt[...]YpwkJc8ycaabA==
60+
bundled deps: 1
61+
bundled files: 0
62+
own files: 5
63+
total files: 5
64+
65+
3666
`

test/lib/commands/pack.js

+18
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,24 @@ t.test('should log output as valid json', async t => {
7777
t.ok(fs.statSync(path.resolve(npm.prefix, filename)))
7878
})
7979

80+
t.test('should log scoped package output as valid json', async t => {
81+
const { npm, outputs, logs } = await loadMockNpm(t, {
82+
prefixDir: {
83+
'package.json': JSON.stringify({
84+
name: '@myscope/test-package',
85+
version: '1.0.0',
86+
}),
87+
},
88+
})
89+
process.chdir(npm.prefix)
90+
npm.config.set('json', true)
91+
await npm.exec('pack', [])
92+
const filename = 'myscope-test-package-1.0.0.tgz'
93+
t.matchSnapshot(outputs.map(JSON.parse), 'outputs as json')
94+
t.matchSnapshot(logs.notice.map(([, m]) => m), 'logs pack contents')
95+
t.ok(fs.statSync(path.resolve(npm.prefix, filename)))
96+
})
97+
8098
t.test('dry run', async t => {
8199
const { npm, outputs, logs } = await loadMockNpm(t, {
82100
prefixDir: {

test/lib/utils/tar.js

+32
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,38 @@ t.test('should log tarball contents', async (t) => {
5151
t.matchSnapshot(printLogs(tarballContents))
5252
})
5353

54+
t.test('should log tarball contents of a scoped package', async (t) => {
55+
const testDir = t.testdir({
56+
'package.json': JSON.stringify({
57+
name: '@myscope/my-cool-pkg',
58+
version: '1.0.0',
59+
bundleDependencies: [
60+
'bundle-dep',
61+
],
62+
dependencies: {
63+
'bundle-dep': '1.0.0',
64+
},
65+
}),
66+
cat: 'meow',
67+
chai: 'blub',
68+
dog: 'woof',
69+
node_modules: {
70+
'bundle-dep': {
71+
'package.json': '',
72+
},
73+
},
74+
})
75+
76+
const tarball = await pack(testDir)
77+
const tarballContents = await getContents({
78+
_id: '1',
79+
name: '@myscope/my-cool-pkg',
80+
version: '1.0.0',
81+
}, tarball)
82+
83+
t.matchSnapshot(printLogs(tarballContents))
84+
})
85+
5486
t.test('should log tarball contents with unicode', async (t) => {
5587
const { logTar } = mockTar({
5688
notice: (str) => {

0 commit comments

Comments
 (0)