fix: packages with default peer dependencies (#5210)

This commit is contained in:
Zoltan Kochan
2022-08-17 11:41:54 +03:00
committed by GitHub
parent d64bc1a050
commit 071aa18423
4 changed files with 73 additions and 20 deletions

View File

@@ -0,0 +1,6 @@
---
"pnpm": patch
"@pnpm/resolve-dependencies": patch
---
When the same package is both in "peerDependencies" and in "dependencies", treat this dependency as a peer dependency if it may be resolved from the dependencies of parent packages [#5210](https://github.com/pnpm/pnpm/pull/5210).

View File

@@ -0,0 +1,54 @@
import path from 'path'
import { prepareEmpty } from '@pnpm/prepare'
import { addDistTag } from '@pnpm/registry-mock'
import { addDependenciesToPackage } from '@pnpm/core'
import deepRequireCwd from 'deep-require-cwd'
import exists from 'path-exists'
import { testDefaults } from '../utils'
test('package with default peer dependency, when auto install peers is on', async () => {
await addDistTag({ package: 'dep-of-pkg-with-1-dep', version: '100.1.0', distTag: 'latest' })
const project = prepareEmpty()
await addDependenciesToPackage({}, ['has-default-peer'], await testDefaults({ autoInstallPeers: true }))
const lockfile = await project.readLockfile()
expect(lockfile.packages).toHaveProperty(['/dep-of-pkg-with-1-dep/100.1.0'])
})
test('don\'t install the default peer dependency when it may be resolved from parent packages', async () => {
const project = prepareEmpty()
await addDependenciesToPackage({}, ['has-default-peer', 'dep-of-pkg-with-1-dep@101.0.0'], await testDefaults())
const lockfile = await project.readLockfile()
expect(Object.keys(lockfile.packages)).toStrictEqual([
'/dep-of-pkg-with-1-dep/101.0.0',
'/has-default-peer/1.0.0_ptp3ffmxbab2qqs6nxppnituqi',
])
})
test('install the default peer dependency when it cannot be resolved from parent packages', async () => {
const project = prepareEmpty()
await addDependenciesToPackage({}, ['has-default-peer'], await testDefaults())
const lockfile = await project.readLockfile()
expect(Object.keys(lockfile.packages)).toStrictEqual([
'/dep-of-pkg-with-1-dep/100.0.0',
'/has-default-peer/1.0.0',
])
})
test('package that resolves its own peer dependency', async () => {
await addDistTag({ package: 'peer-c', version: '1.0.0', distTag: 'latest' })
const project = prepareEmpty()
await addDependenciesToPackage({}, ['pkg-with-resolved-peer', 'peer-c@2.0.0'], await testDefaults())
expect(deepRequireCwd(['pkg-with-resolved-peer', 'peer-c', './package.json']).version).toBe('2.0.0')
expect(await exists(path.resolve('node_modules/.pnpm/pkg-with-resolved-peer@1.0.0_peer-c@2.0.0/node_modules/pkg-with-resolved-peer'))).toBeTruthy()
const lockfile = await project.readLockfile()
expect(lockfile.packages['/pkg-with-resolved-peer/1.0.0_peer-c@2.0.0']?.peerDependencies).toStrictEqual({ 'peer-c': '*' })
expect(lockfile.packages['/pkg-with-resolved-peer/1.0.0_peer-c@2.0.0'].dependencies).toHaveProperty(['peer-c'])
expect(lockfile.packages['/pkg-with-resolved-peer/1.0.0_peer-c@2.0.0'].optionalDependencies).toHaveProperty(['peer-b'])
})

View File

@@ -566,26 +566,6 @@ test('run pre/postinstall scripts of each variations of packages with peer depen
await okFile(path.join(pkgVariation2, 'pkg-with-events-and-peers', 'generated-by-postinstall.js'))
})
test('package that resolves its own peer dependency', async () => {
// TODO: investigate how npm behaves in such situations
// should there be a warning printed?
// does it currently print a warning that peer dependency is not resolved?
await addDistTag({ package: 'peer-c', version: '1.0.0', distTag: 'latest' })
const project = prepareEmpty()
await addDependenciesToPackage({}, ['pkg-with-resolved-peer', 'peer-c@2.0.0'], await testDefaults())
expect(deepRequireCwd(['pkg-with-resolved-peer', 'peer-c', './package.json']).version).toBe('1.0.0')
expect(await exists(path.resolve('node_modules/.pnpm/pkg-with-resolved-peer@1.0.0/node_modules/pkg-with-resolved-peer'))).toBeTruthy()
const lockfile = await project.readLockfile()
expect(lockfile.packages['/pkg-with-resolved-peer/1.0.0']).not.toHaveProperty(['peerDependencies'])
expect(lockfile.packages['/pkg-with-resolved-peer/1.0.0'].dependencies).toHaveProperty(['peer-c'])
expect(lockfile.packages['/pkg-with-resolved-peer/1.0.0'].optionalDependencies).toHaveProperty(['peer-b'])
})
test('package that has parent as peer dependency', async () => {
const project = prepareEmpty()
await addDependenciesToPackage({}, ['has-alpha', 'alpha'], await testDefaults())

View File

@@ -820,6 +820,19 @@ async function resolveDependency (
if (ctx.readPackageHook != null) {
pkg = await ctx.readPackageHook(pkg)
}
if (pkg.peerDependencies && pkg.dependencies) {
if (ctx.autoInstallPeers) {
for (const peerDep of Object.keys(pkg.peerDependencies)) {
delete pkg.dependencies[peerDep]
}
} else {
for (const peerDep of Object.keys(pkg.peerDependencies)) {
if (options.parentPkgAliases[peerDep]) {
delete pkg.dependencies[peerDep]
}
}
}
}
if (!pkg.name) { // TODO: don't fail on optional dependencies
throw new PnpmError('MISSING_PACKAGE_NAME', `Can't install ${wantedDependency.pref}: Missing package name`)
}