diff --git a/docs/content/commands/npm-publish.md b/docs/content/commands/npm-publish.md index 536d04988e684..0c1b777c881bb 100644 --- a/docs/content/commands/npm-publish.md +++ b/docs/content/commands/npm-publish.md @@ -118,19 +118,19 @@ tarball that will be compared with the local files by default. #### `access` -* Default: 'restricted' for scoped packages, 'public' for unscoped packages +* Default: 'public' for new packages, existing packages it will not change the + current level * Type: null, "restricted", or "public" -When publishing scoped packages, the access level defaults to `restricted`. -If you want your scoped package to be publicly viewable (and installable) -set `--access=public`. The only valid values for `access` are `public` and -`restricted`. Unscoped packages _always_ have an access level of `public`. +If do not want your scoped package to be publicly viewable (and installable) +set `--access=restricted`. -Note: Using the `--access` flag on the `npm publish` command will only set -the package access level on the initial publish of the package. Any -subsequent `npm publish` commands using the `--access` flag will not have an -effect to the access level. To make changes to the access level after the -initial publish use `npm access`. +Unscoped packages can not be set to `restricted`. + +Note: This defaults to not changing the current access level for existing +packages. Specifying a value of `restricted` or `public` during publish will +change the access for an existing package the same way that `npm access set +status` would. diff --git a/docs/content/using-npm/config.md b/docs/content/using-npm/config.md index 2de35fa2a46c3..e5d9d081feb4a 100644 --- a/docs/content/using-npm/config.md +++ b/docs/content/using-npm/config.md @@ -151,19 +151,19 @@ safer to use a registry-provided authentication bearer token stored in the #### `access` -* Default: 'restricted' for scoped packages, 'public' for unscoped packages +* Default: 'public' for new packages, existing packages it will not change the + current level * Type: null, "restricted", or "public" -When publishing scoped packages, the access level defaults to `restricted`. -If you want your scoped package to be publicly viewable (and installable) -set `--access=public`. The only valid values for `access` are `public` and -`restricted`. Unscoped packages _always_ have an access level of `public`. +If do not want your scoped package to be publicly viewable (and installable) +set `--access=restricted`. -Note: Using the `--access` flag on the `npm publish` command will only set -the package access level on the initial publish of the package. Any -subsequent `npm publish` commands using the `--access` flag will not have an -effect to the access level. To make changes to the access level after the -initial publish use `npm access`. +Unscoped packages can not be set to `restricted`. + +Note: This defaults to not changing the current access level for existing +packages. Specifying a value of `restricted` or `public` during publish will +change the access for an existing package the same way that `npm access set +status` would. diff --git a/lib/commands/publish.js b/lib/commands/publish.js index 64b6dfc513c95..1f281a0bb1d4f 100644 --- a/lib/commands/publish.js +++ b/lib/commands/publish.js @@ -114,10 +114,13 @@ class Publish extends BaseCommand { } } - log.notice( - '', - `Publishing to ${outputRegistry} with tag ${defaultTag}${dryRun ? ' (dry-run)' : ''}` - ) + const access = opts.access === null ? 'default' : opts.access + let msg = `Publishing to ${outputRegistry} with tag ${defaultTag} and ${access} access` + if (dryRun) { + msg = `${msg} (dry-run)` + } + + log.notice('', msg) if (!dryRun) { await otplease(this.npm, opts, opts => libpub(manifest, tarballData, opts)) diff --git a/lib/utils/config/definitions.js b/lib/utils/config/definitions.js index ae38efc32b5ae..5f74eb03b14c8 100644 --- a/lib/utils/config/definitions.js +++ b/lib/utils/config/definitions.js @@ -160,21 +160,19 @@ define('_auth', { define('access', { default: null, defaultDescription: ` - 'restricted' for scoped packages, 'public' for unscoped packages + 'public' for new packages, existing packages it will not change the current level `, type: [null, 'restricted', 'public'], description: ` - When publishing scoped packages, the access level defaults to - \`restricted\`. If you want your scoped package to be publicly viewable - (and installable) set \`--access=public\`. The only valid values for - \`access\` are \`public\` and \`restricted\`. Unscoped packages _always_ - have an access level of \`public\`. - - Note: Using the \`--access\` flag on the \`npm publish\` command will only - set the package access level on the initial publish of the package. Any - subsequent \`npm publish\` commands using the \`--access\` flag will not - have an effect to the access level. To make changes to the access level - after the initial publish use \`npm access\`. + If do not want your scoped package to be publicly viewable (and + installable) set \`--access=restricted\`. + + Unscoped packages can not be set to \`restricted\`. + + Note: This defaults to not changing the current access level for existing + packages. Specifying a value of \`restricted\` or \`public\` during + publish will change the access for an existing package the same way that + \`npm access set status\` would. `, flatten, }) diff --git a/tap-snapshots/test/lib/commands/publish.js.test.cjs b/tap-snapshots/test/lib/commands/publish.js.test.cjs index 3b215960fa37e..28211f7794cba 100644 --- a/tap-snapshots/test/lib/commands/publish.js.test.cjs +++ b/tap-snapshots/test/lib/commands/publish.js.test.cjs @@ -51,7 +51,7 @@ Array [ ], Array [ "", - "Publishing to https://registry.npmjs.org/ with tag latest (dry-run)", + "Publishing to https://registry.npmjs.org/ with tag latest and default access (dry-run)", ], ] ` @@ -72,7 +72,7 @@ exports[`test/lib/commands/publish.js TAP json > must match snapshot 1`] = ` Array [ Array [ "", - "Publishing to https://registry.npmjs.org/ with tag latest", + "Publishing to https://registry.npmjs.org/ with tag latest and default access", ], ] ` @@ -112,6 +112,53 @@ Array [ ] ` +exports[`test/lib/commands/publish.js TAP public access > must match snapshot 1`] = ` +Array [ + Array [ + "", + ], + Array [ + "", + "package: @npm/test-package@1.0.0", + ], + Array [ + "=== Tarball Contents ===", + ], + Array [ + "", + "55B package.json", + ], + Array [ + "=== Tarball Details ===", + ], + Array [ + "", + String( + name: @npm/test-package + version: 1.0.0 + filename: @npm/test-package-1.0.0.tgz + package size: 147 B + unpacked size: 55 B + shasum:{sha} + integrity:{sha} + total files: 1 + ), + ], + Array [ + "", + "", + ], + Array [ + "", + "Publishing to https://registry.npmjs.org/ with tag latest and public access", + ], +] +` + +exports[`test/lib/commands/publish.js TAP public access > new package version 1`] = ` ++ @npm/test-package@1.0.0 +` + exports[`test/lib/commands/publish.js TAP re-loads publishConfig.registry if added during script process > new package version 1`] = ` + test-package@1.0.0 ` @@ -120,6 +167,53 @@ exports[`test/lib/commands/publish.js TAP respects publishConfig.registry, runs ` +exports[`test/lib/commands/publish.js TAP restricted access > must match snapshot 1`] = ` +Array [ + Array [ + "", + ], + Array [ + "", + "package: @npm/test-package@1.0.0", + ], + Array [ + "=== Tarball Contents ===", + ], + Array [ + "", + "55B package.json", + ], + Array [ + "=== Tarball Details ===", + ], + Array [ + "", + String( + name: @npm/test-package + version: 1.0.0 + filename: @npm/test-package-1.0.0.tgz + package size: 147 B + unpacked size: 55 B + shasum:{sha} + integrity:{sha} + total files: 1 + ), + ], + Array [ + "", + "", + ], + Array [ + "", + "Publishing to https://registry.npmjs.org/ with tag latest and restricted access", + ], +] +` + +exports[`test/lib/commands/publish.js TAP restricted access > new package version 1`] = ` ++ @npm/test-package@1.0.0 +` + exports[`test/lib/commands/publish.js TAP scoped _auth config scoped registry > new package version 1`] = ` + @npm/test-package@1.0.0 ` @@ -165,7 +259,7 @@ Array [ ], Array [ "", - "Publishing to https://registry.npmjs.org/ with tag latest", + "Publishing to https://registry.npmjs.org/ with tag latest and default access", ], ] ` diff --git a/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs b/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs index df9313270d056..1005b9e4df112 100644 --- a/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs +++ b/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs @@ -180,19 +180,19 @@ safer to use a registry-provided authentication bearer token stored in the exports[`test/lib/utils/config/definitions.js TAP > config description for access 1`] = ` #### \`access\` -* Default: 'restricted' for scoped packages, 'public' for unscoped packages +* Default: 'public' for new packages, existing packages it will not change the + current level * Type: null, "restricted", or "public" -When publishing scoped packages, the access level defaults to \`restricted\`. -If you want your scoped package to be publicly viewable (and installable) -set \`--access=public\`. The only valid values for \`access\` are \`public\` and -\`restricted\`. Unscoped packages _always_ have an access level of \`public\`. +If do not want your scoped package to be publicly viewable (and installable) +set \`--access=restricted\`. -Note: Using the \`--access\` flag on the \`npm publish\` command will only set -the package access level on the initial publish of the package. Any -subsequent \`npm publish\` commands using the \`--access\` flag will not have an -effect to the access level. To make changes to the access level after the -initial publish use \`npm access\`. +Unscoped packages can not be set to \`restricted\`. + +Note: This defaults to not changing the current access level for existing +packages. Specifying a value of \`restricted\` or \`public\` during publish will +change the access for an existing package the same way that \`npm access set +status\` would. ` exports[`test/lib/utils/config/definitions.js TAP > config description for all 1`] = ` diff --git a/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs b/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs index 89ca7c952b182..e14b88464237c 100644 --- a/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs +++ b/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs @@ -24,19 +24,19 @@ safer to use a registry-provided authentication bearer token stored in the #### \`access\` -* Default: 'restricted' for scoped packages, 'public' for unscoped packages +* Default: 'public' for new packages, existing packages it will not change the + current level * Type: null, "restricted", or "public" -When publishing scoped packages, the access level defaults to \`restricted\`. -If you want your scoped package to be publicly viewable (and installable) -set \`--access=public\`. The only valid values for \`access\` are \`public\` and -\`restricted\`. Unscoped packages _always_ have an access level of \`public\`. +If do not want your scoped package to be publicly viewable (and installable) +set \`--access=restricted\`. -Note: Using the \`--access\` flag on the \`npm publish\` command will only set -the package access level on the initial publish of the package. Any -subsequent \`npm publish\` commands using the \`--access\` flag will not have an -effect to the access level. To make changes to the access level after the -initial publish use \`npm access\`. +Unscoped packages can not be set to \`restricted\`. + +Note: This defaults to not changing the current access level for existing +packages. Specifying a value of \`restricted\` or \`public\` during publish will +change the access for an existing package the same way that \`npm access set +status\` would. diff --git a/test/lib/commands/publish.js b/test/lib/commands/publish.js index 16b79df532d82..995abff88c2c1 100644 --- a/test/lib/commands/publish.js +++ b/test/lib/commands/publish.js @@ -28,7 +28,7 @@ t.cleanSnapshot = data => { t.test('respects publishConfig.registry, runs appropriate scripts', async t => { const { npm, joinedOutput, prefix } = await loadMockNpm(t, { config: { - loglevel: 'silent', // prevent scripts from leaking to stdout during the test + loglevel: 'silent', [`${alternateRegistry.slice(6)}/:_authToken`]: 'test-other-token', }, prefixDir: { @@ -730,3 +730,65 @@ t.test('scoped _auth config scoped registry', async t => { await npm.exec('publish', []) t.matchSnapshot(joinedOutput(), 'new package version') }) + +t.test('restricted access', async t => { + const spec = npa('@npm/test-package') + const { npm, joinedOutput, logs } = await loadMockNpm(t, { + config: { + ...auth, + access: 'restricted', + }, + prefixDir: { + 'package.json': JSON.stringify({ + name: '@npm/test-package', + version: '1.0.0', + }, null, 2), + }, + globals: ({ prefix }) => ({ + 'process.cwd': () => prefix, + }), + }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: token, + }) + registry.nock.put(`/${spec.escapedName}`, body => { + t.equal(body.access, 'restricted', 'access is explicitly set to restricted') + return true + }).reply(200, {}) + await npm.exec('publish', []) + t.matchSnapshot(joinedOutput(), 'new package version') + t.matchSnapshot(logs.notice) +}) + +t.test('public access', async t => { + const spec = npa('@npm/test-package') + const { npm, joinedOutput, logs } = await loadMockNpm(t, { + config: { + ...auth, + access: 'public', + }, + prefixDir: { + 'package.json': JSON.stringify({ + name: '@npm/test-package', + version: '1.0.0', + }, null, 2), + }, + globals: ({ prefix }) => ({ + 'process.cwd': () => prefix, + }), + }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: token, + }) + registry.nock.put(`/${spec.escapedName}`, body => { + t.equal(body.access, 'public', 'access is explicitly set to public') + return true + }).reply(200, {}) + await npm.exec('publish', []) + t.matchSnapshot(joinedOutput(), 'new package version') + t.matchSnapshot(logs.notice) +})