mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-28 02:53:15 -04:00
fix: packages with default peer dependencies (#5210)
This commit is contained in:
6
.changeset/wild-files-reply.md
Normal file
6
.changeset/wild-files-reply.md
Normal 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).
|
||||
54
packages/core/test/install/defaultPeerDependencies.ts
Normal file
54
packages/core/test/install/defaultPeerDependencies.ts
Normal 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'])
|
||||
})
|
||||
@@ -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())
|
||||
|
||||
@@ -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`)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user