mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-27 00:58:11 -05:00
fix: dedupe-peer-dependents on a subset of projects (#6173)
close #6171
This commit is contained in:
6
.changeset/seven-crews-roll.md
Normal file
6
.changeset/seven-crews-roll.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/plugin-commands-installation": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
`dedupe-peer-dependents` should work when running an install command on a subset of workspace projects [#6171](https://github.com/pnpm/pnpm/issues/6171).
|
||||
@@ -9,7 +9,7 @@ import { filterPkgsBySelectorObjects } from '@pnpm/filter-workspace-packages'
|
||||
import { arrayOfWorkspacePackagesToMap, findWorkspacePackages } from '@pnpm/find-workspace-packages'
|
||||
import { rebuildProjects } from '@pnpm/plugin-commands-rebuild'
|
||||
import { createOrConnectStoreController, CreateStoreControllerOptions } from '@pnpm/store-connection-manager'
|
||||
import { IncludedDependencies, Project } from '@pnpm/types'
|
||||
import { IncludedDependencies, Project, ProjectsGraph } from '@pnpm/types'
|
||||
import {
|
||||
install,
|
||||
mutateModulesInSingleProject,
|
||||
@@ -39,6 +39,7 @@ export type InstallDepsOptions = Pick<Config,
|
||||
| 'bail'
|
||||
| 'bin'
|
||||
| 'cliOptions'
|
||||
| 'dedupePeerDependents'
|
||||
| 'depth'
|
||||
| 'dev'
|
||||
| 'engineStrict'
|
||||
@@ -145,11 +146,16 @@ when running add/update with the --workspace option')
|
||||
})
|
||||
}
|
||||
|
||||
let allProjectsGraph = selectedProjectsGraph
|
||||
if (!allProjectsGraph[opts.workspaceDir]) {
|
||||
allProjectsGraph = {
|
||||
...allProjectsGraph,
|
||||
...selectProjectByDir(allProjects, opts.workspaceDir),
|
||||
let allProjectsGraph!: ProjectsGraph
|
||||
if (opts.dedupePeerDependents) {
|
||||
allProjectsGraph = opts.allProjectsGraph!
|
||||
} else {
|
||||
allProjectsGraph = selectedProjectsGraph
|
||||
if (!allProjectsGraph[opts.workspaceDir]) {
|
||||
allProjectsGraph = {
|
||||
...allProjectsGraph,
|
||||
...selectProjectByDir(allProjects, opts.workspaceDir),
|
||||
}
|
||||
}
|
||||
}
|
||||
await recursive(allProjects,
|
||||
|
||||
@@ -43,6 +43,7 @@ import { PreferredVersions } from '@pnpm/resolver-base'
|
||||
|
||||
type RecursiveOptions = CreateStoreControllerOptions & Pick<Config,
|
||||
| 'bail'
|
||||
| 'dedupePeerDependents'
|
||||
| 'depth'
|
||||
| 'globalPnpmfile'
|
||||
| 'hoistPattern'
|
||||
@@ -245,17 +246,23 @@ export async function recursive (
|
||||
}
|
||||
}))
|
||||
if (!opts.selectedProjectsGraph[opts.workspaceDir] && manifestsByPath[opts.workspaceDir] != null) {
|
||||
const localConfig = await memReadLocalConfig(opts.workspaceDir)
|
||||
const modulesDir = localConfig.modulesDir ?? opts.modulesDir
|
||||
const { manifest, writeProjectManifest } = manifestsByPath[opts.workspaceDir]
|
||||
const { writeProjectManifest } = manifestsByPath[opts.workspaceDir]
|
||||
writeProjectManifests.push(writeProjectManifest)
|
||||
mutatedImporters.push({
|
||||
buildIndex: 0,
|
||||
manifest,
|
||||
modulesDir,
|
||||
mutation: 'install',
|
||||
rootDir: opts.workspaceDir,
|
||||
} as MutatedProject)
|
||||
})
|
||||
}
|
||||
if (opts.dedupePeerDependents) {
|
||||
for (const rootDir of Object.keys(opts.allProjectsGraph)) {
|
||||
if (opts.selectedProjectsGraph[rootDir]) continue
|
||||
const { writeProjectManifest } = manifestsByPath[rootDir]
|
||||
writeProjectManifests.push(writeProjectManifest)
|
||||
mutatedImporters.push({
|
||||
mutation: 'install',
|
||||
rootDir,
|
||||
})
|
||||
}
|
||||
}
|
||||
if ((mutatedImporters.length === 0) && cmdFullName === 'update' && opts.depth === 0) {
|
||||
throw new PnpmError('NO_PACKAGE_IN_DEPENDENCIES',
|
||||
|
||||
48
pnpm/test/monorepo/dedupePeers.test.ts
Normal file
48
pnpm/test/monorepo/dedupePeers.test.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { writeFileSync } from 'fs'
|
||||
import path from 'path'
|
||||
import { WANTED_LOCKFILE } from '@pnpm/constants'
|
||||
import { Lockfile } from '@pnpm/lockfile-types'
|
||||
import { preparePackages } from '@pnpm/prepare'
|
||||
import { addDistTag } from '@pnpm/registry-mock'
|
||||
import { sync as readYamlFile } from 'read-yaml-file'
|
||||
import { createPeersFolderSuffix } from '@pnpm/dependency-path'
|
||||
import { sync as writeYamlFile } from 'write-yaml-file'
|
||||
import { execPnpm } from '../utils'
|
||||
|
||||
test('deduplicate packages that have peers, when adding new dependency in a workspace', async () => {
|
||||
await addDistTag({ package: '@pnpm.e2e/abc-parent-with-ab', version: '1.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-a', version: '1.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-b', version: '1.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: '@pnpm.e2e/peer-c', version: '1.0.0', distTag: 'latest' })
|
||||
|
||||
preparePackages([
|
||||
{
|
||||
location: 'project-1',
|
||||
package: {
|
||||
name: 'project-1',
|
||||
|
||||
dependencies: {
|
||||
'@pnpm.e2e/abc-grand-parent-with-c': '1.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
location: 'project-2',
|
||||
package: {
|
||||
name: 'project-2',
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
writeYamlFile('pnpm-workspace.yaml', { packages: ['**', '!store/**'] })
|
||||
writeFileSync('.npmrc', `dedupe-peer-dependents=true
|
||||
auto-install-peers=false`, 'utf8')
|
||||
await execPnpm(['install'])
|
||||
await execPnpm(['--filter=project-2', 'add', '@pnpm.e2e/abc@1.0.0'])
|
||||
|
||||
const lockfile = readYamlFile<Lockfile>(path.resolve(WANTED_LOCKFILE))
|
||||
const depPaths = Object.keys(lockfile.packages ?? {})
|
||||
expect(depPaths.length).toBe(8)
|
||||
expect(depPaths).toContain(`/@pnpm.e2e/abc/1.0.0${createPeersFolderSuffix([{ name: '@pnpm.e2e/peer-a', version: '1.0.0' }, { name: '@pnpm.e2e/peer-b', version: '1.0.0' }, { name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
|
||||
expect(depPaths).toContain(`/@pnpm.e2e/abc-parent-with-ab/1.0.0${createPeersFolderSuffix([{ name: '@pnpm.e2e/peer-c', version: '1.0.0' }])}`)
|
||||
})
|
||||
Reference in New Issue
Block a user