feat: "pnpm i" in a workspace is "pnpm i -r"

When `use-beta-cli` is true, `pnpm i` is the same as
`pnpm i -r` inside a workspace. Also, adding deps
to the root workspace package is only allowed with the
`--ignore-workspace-root-check` or `-W` flag.

close #1444
PR #1913
This commit is contained in:
Zoltan Kochan
2019-07-13 19:49:15 +03:00
committed by GitHub
parent a6ec2b2228
commit 1086cdfd7a
4 changed files with 128 additions and 1 deletions

View File

@@ -3,6 +3,7 @@ import { Registries } from '@pnpm/types'
export interface PnpmConfigs extends Record<string, any> { // tslint:disable-line
bail: boolean,
cliArgs: Record<string, any>, // tslint:disable-line
useBetaCli: boolean,
extraBinPaths: string[],
filter: string[],
rawNpmConfig: Record<string, any>, // tslint:disable-line
@@ -81,4 +82,5 @@ export interface PnpmConfigs extends Record<string, any> { // tslint:disable-lin
resolutionStrategy: 'fast' | 'fewer-dependencies',
registries: Registries,
ignoreWorkspaceRootCheck: boolean,
}

View File

@@ -32,6 +32,7 @@ export const types = Object.assign({
'ignore-pnpmfile': Boolean,
'ignore-stop-requests': Boolean,
'ignore-upload-requests': Boolean,
'ignore-workspace-root-check': Boolean,
'independent-leaves': Boolean,
'latest': Boolean,
'link-workspace-packages': Boolean,
@@ -64,6 +65,7 @@ export const types = Object.assign({
'sort': Boolean,
'store': path,
'strict-peer-dependencies': Boolean,
'use-beta-cli': Boolean,
'use-running-store-server': Boolean,
'use-store-server': Boolean,
'verify-store-integrity': Boolean,
@@ -129,6 +131,7 @@ export default async (
'fetch-retry-maxtimeout': 60000,
'fetch-retry-mintimeout': 10000,
'globalconfig': npmDefaults.globalconfig,
'ignore-workspace-root-check': false,
'latest': false,
'link-workspace-packages': true,
'lock': true,
@@ -143,6 +146,7 @@ export default async (
'sort': true,
'strict-peer-dependencies': false,
'unsafe-perm': npmDefaults['unsafe-perm'],
'use-beta-cli': false,
'userconfig': npmDefaults.userconfig,
'workspace-concurrency': 4,
'workspace-prefix': workspacePrefix,

View File

@@ -136,6 +136,7 @@ export default async function run (argv: string[]) {
'shared-workspace-lockfile': ['--shared-workspace-shrinkwrap'],
'frozen-lockfile': ['--frozen-shrinkwrap'],
'prefer-frozen-lockfile': ['--prefer-frozen-shrinkwrap'],
'W': ['--ignore-workspace-root-check'],
}
// tslint:enable
const cliConf = nopt(types, shortHands, argv, 0)
@@ -201,6 +202,30 @@ export default async function run (argv: string[]) {
return
}
if (
opts.useBetaCli &&
cmd === 'install' &&
typeof opts.workspacePrefix === 'string'
) {
if (cliArgs.length === 0) {
subCmd = cmd
cmd = 'recursive'
cliArgs.unshift(subCmd)
} else if (
opts.workspacePrefix === opts.prefix &&
!opts.ignoreWorkspaceRootCheck
) {
// Reporting is not initialized at this point, so just printing the error
console.error(`${chalk.bgRed.black('\u2009ERROR\u2009')} ${
chalk.red('Running this command will add the dependency to the workspace root, ' +
'which might not be what you want - if you really meant it, ' +
'make it explicit by running this command again with the -W flag (or --ignore-workspace-root-check).')}`)
console.log(`For help, run: pnpm help ${cmd}`)
process.exit(1)
return
}
}
const selfUpdate = opts.global && (cmd === 'install' || cmd === 'update') && cliConf.argv.remain.includes(packageManager.name)
// Don't check for updates

View File

@@ -1,5 +1,5 @@
import { Lockfile } from '@pnpm/lockfile-types'
import { preparePackages } from '@pnpm/prepare'
import prepare, { preparePackages } from '@pnpm/prepare'
import isCI = require('is-ci')
import isWindows = require('is-windows')
import makeDir = require('make-dir')
@@ -12,6 +12,7 @@ import writeJsonFile = require('write-json-file')
import writeYamlFile = require('write-yaml-file')
import {
execPnpm,
execPnpmSync,
retryLoadJsonFile,
spawn,
} from '../utils'
@@ -107,6 +108,66 @@ test('recursive install using "install --recursive"', async (t: tape.Test) => {
t.ok(projects['project-2'].requireModule('is-negative'))
})
test('installation in the root of a workspace with "install" when the "use-beta-cli" config is true', async (t: tape.Test) => {
const projects = preparePackages(t, [
{
name: 'project-1',
version: '1.0.0',
dependencies: {
'is-positive': '1.0.0',
},
},
{
name: 'project-2',
version: '1.0.0',
dependencies: {
'is-negative': '1.0.0',
},
},
])
await fs.writeFile('pnpm-workspace.yaml', '', 'utf8')
await fs.writeFile('.npmrc', 'use-beta-cli=true', 'utf8')
await execPnpm('install')
t.ok(projects['project-1'].requireModule('is-positive'))
t.ok(projects['project-2'].requireModule('is-negative'))
})
test('installation in a subdirectory of a workspace with "install" when the "use-beta-cli" config is true', async (t: tape.Test) => {
const projects = preparePackages(t, [
{
name: 'project-1',
version: '1.0.0',
dependencies: {
'is-positive': '1.0.0',
},
},
{
name: 'project-2',
version: '1.0.0',
dependencies: {
'is-negative': '1.0.0',
},
},
])
await fs.writeFile('pnpm-workspace.yaml', '', 'utf8')
await fs.writeFile('.npmrc', 'use-beta-cli=true', 'utf8')
process.chdir('project-1')
await execPnpm('install')
t.ok(projects['project-1'].requireModule('is-positive'))
t.ok(projects['project-2'].requireModule('is-negative'))
})
test('recursive install should install in whole workspace even when executed in a subdirectory', async (t: tape.Test) => {
const projects = preparePackages(t, [
{
@@ -1153,3 +1214,38 @@ test('recursive install --no-bail', async (t: tape.Test) => {
t.ok(projects['project-2'].requireModule('is-negative'))
})
test('adding new dependency in the root should fail if --ignore-workspace-root-check is not used', async (t: tape.Test) => {
const project = prepare(t)
await fs.writeFile('pnpm-workspace.yaml', '', 'utf8')
await fs.writeFile('.npmrc', 'use-beta-cli=true', 'utf8')
{
const { status, stderr } = execPnpmSync('add', 'is-positive')
t.equal(status, 1)
t.ok(
stderr.toString().includes(
'Running this command will add the dependency to the workspace root, ' +
'which might not be what you want - if you really meant it, ' +
'make it explicit by running this command again with the -W flag (or --ignore-workspace-root-check).'
)
)
}
{
const { status } = execPnpmSync('add', 'is-positive', '--ignore-workspace-root-check')
t.equal(status, 0)
await project.has('is-positive')
}
{
const { status } = execPnpmSync('add', 'is-negative', '-W')
t.equal(status, 0)
await project.has('is-negative')
}
})