feat: add an option to list and why to exclude peer dependencies from the output (#8506)

This commit is contained in:
Zoltan Kochan
2024-09-08 22:26:33 +02:00
committed by GitHub
parent db420ab592
commit 3af07cb839
7 changed files with 97 additions and 3 deletions

View File

@@ -0,0 +1,8 @@
---
"@pnpm/plugin-commands-listing": minor
"@pnpm/reviewing.dependencies-hierarchy": minor
"@pnpm/list": minor
"pnpm": minor
---
Support for a new CLI flag, `--exclude-peers`, added to the `list` and `why` commands. When `--exclude-peers` is used, peer dependencies are not printed in the results, but dependencies of peer dependencies are still scanned [#8506](https://github.com/pnpm/pnpm/pull/8506).

View File

@@ -34,6 +34,7 @@ export async function buildDependenciesHierarchy (
projectPaths: string[] | undefined,
maybeOpts: {
depth: number
excludePeerDependencies?: boolean
include?: { [dependenciesField in DependenciesField]: boolean }
registries?: Registries
onlyProjects?: boolean
@@ -70,6 +71,7 @@ export async function buildDependenciesHierarchy (
const opts = {
depth: maybeOpts.depth || 0,
excludePeerDependencies: maybeOpts.excludePeerDependencies,
include: maybeOpts.include ?? {
dependencies: true,
devDependencies: true,
@@ -103,6 +105,7 @@ async function dependenciesHierarchyForPackage (
wantedLockfile: Lockfile | null,
opts: {
depth: number
excludePeerDependencies?: boolean
include: { [dependenciesField in DependenciesField]: boolean }
registries: Registries
onlyProjects?: boolean
@@ -127,6 +130,7 @@ async function dependenciesHierarchyForPackage (
const depTypes = detectDepTypes(currentLockfile)
const getChildrenTree = getTree.bind(null, {
currentPackages: currentLockfile.packages ?? {},
excludePeerDependencies: opts.excludePeerDependencies,
importers: currentLockfile.importers,
includeOptionalDependencies: opts.include.optionalDependencies,
depTypes,
@@ -134,7 +138,6 @@ async function dependenciesHierarchyForPackage (
onlyProjects: opts.onlyProjects,
rewriteLinkVersionDir: projectPath,
maxDepth: opts.depth,
modulesDir,
registries: opts.registries,
search: opts.search,
skipped: opts.skipped,

View File

@@ -13,6 +13,7 @@ interface GetTreeOpts {
maxDepth: number
rewriteLinkVersionDir: string
includeOptionalDependencies: boolean
excludePeerDependencies?: boolean
lockfileDir: string
onlyProjects?: boolean
search?: SearchFunction
@@ -209,7 +210,9 @@ function getTreeHelper (
if (matchedSearched) {
newEntry.searched = true
}
resultDependencies.push(newEntry)
if (!newEntry.isPeer || !opts.excludePeerDependencies || newEntry.dependencies?.length) {
resultDependencies.push(newEntry)
}
}
})

View File

@@ -550,4 +550,68 @@ describe('getTree', () => {
])
})
})
test('exclude peers', () => {
const version = '1.0.0'
const currentPackages = {
'foo@1.0.0': {
dependencies: {
peer1: '1.0.0',
peer2: '1.0.0',
qar: '1.0.0',
},
peerDependencies: {
peer1: '^1.0.0',
peer2: '^1.0.0',
},
resolution: { integrity: '000' },
},
'bar@1.0.0': {
resolution: { integrity: '000' },
},
'qar@1.0.0': {
resolution: { integrity: '000' },
},
'peer1@1.0.0': {
dependencies: {
bar: '1.0.0',
},
resolution: { integrity: '000' },
},
'peer2@1.0.0': {
dependencies: {},
resolution: { integrity: '000' },
},
}
const rootNodeId: TreeNodeId = { type: 'package', depPath: refToRelativeOrThrow(version, 'foo') }
const getTreeArgs = {
depTypes: {},
excludePeerDependencies: true,
maxDepth: 3,
rewriteLinkVersionDir: '',
virtualStoreDir: '.pnpm',
importers: {},
includeOptionalDependencies: false,
lockfileDir: '',
skipped: new Set<string>(),
registries: {
default: 'mock-registry-for-testing.example',
},
currentPackages,
wantedPackages: currentPackages,
}
const result = normalizePackageNodeForTesting(getTree({ ...getTreeArgs, maxDepth: 9999, virtualStoreDirMaxLength: 120 }, rootNodeId))
expect(result).toEqual([
expect.objectContaining({
alias: 'peer1',
dependencies: [
expect.objectContaining({
alias: 'bar',
}),
],
}),
expect.objectContaining({ alias: 'qar', dependencies: undefined }),
])
})
})

View File

@@ -59,6 +59,7 @@ export async function searchForPackages (
projectPaths: string[],
opts: {
depth: number
excludePeerDependencies?: boolean
lockfileDir: string
include?: { [dependenciesField in DependenciesField]: boolean }
onlyProjects?: boolean
@@ -72,6 +73,7 @@ export async function searchForPackages (
return Promise.all(
Object.entries(await buildDependenciesHierarchy(projectPaths, {
depth: opts.depth,
excludePeerDependencies: opts.excludePeerDependencies,
include: opts.include,
lockfileDir: opts.lockfileDir,
onlyProjects: opts.onlyProjects,
@@ -130,6 +132,7 @@ export async function list (
maybeOpts: {
alwaysPrintRootPackage?: boolean
depth?: number
excludePeerDependencies?: boolean
lockfileDir: string
long?: boolean
include?: { [dependenciesField in DependenciesField]: boolean }
@@ -152,6 +155,7 @@ export async function list (
}, {} as Record<string, DependenciesHierarchy>)
: await buildDependenciesHierarchy(projectPaths, {
depth: opts.depth,
excludePeerDependencies: maybeOpts?.excludePeerDependencies,
include: maybeOpts?.include,
lockfileDir: maybeOpts?.lockfileDir,
onlyProjects: maybeOpts?.onlyProjects,

View File

@@ -7,6 +7,11 @@ import pick from 'ramda/src/pick'
import renderHelp from 'render-help'
import { listRecursive } from './recursive'
export const EXCLUDE_PEERS_HELP = {
description: 'Exclude peer dependencies',
name: '--exclude-peers',
}
export function rcOptionsTypes (): Record<string, unknown> {
return pick([
'depth',
@@ -24,6 +29,7 @@ export function rcOptionsTypes (): Record<string, unknown> {
export const cliOptionsTypes = (): Record<string, unknown> => ({
...rcOptionsTypes(),
'exclude-peers': Boolean,
'only-projects': Boolean,
recursive: Boolean,
})
@@ -100,6 +106,7 @@ For options that may be used with `-r`, see "pnpm help recursive"',
description: "Don't display packages from `optionalDependencies`",
name: '--no-optional',
},
EXCLUDE_PEERS_HELP,
OPTIONS.globalDir,
...UNIVERSAL_OPTIONS,
],
@@ -125,6 +132,7 @@ export type ListCommandOptions = Pick<Config,
> & Partial<Pick<Config, 'cliOptions'>> & {
alwaysPrintRootPackage?: boolean
depth?: number
excludePeers?: boolean
lockfileDir?: string
long?: boolean
parseable?: boolean
@@ -160,6 +168,7 @@ export async function render (
opts: {
alwaysPrintRootPackage?: boolean
depth?: number
excludePeers?: boolean
include: IncludedDependencies
lockfileDir: string
long?: boolean
@@ -173,6 +182,7 @@ export async function render (
const listOpts = {
alwaysPrintRootPackage: opts.alwaysPrintRootPackage,
depth: opts.depth ?? 0,
excludePeerDependencies: opts.excludePeers,
include: opts.include,
lockfileDir: opts.lockfileDir,
long: opts.long,

View File

@@ -4,7 +4,7 @@ import { types as allTypes } from '@pnpm/config'
import { PnpmError } from '@pnpm/error'
import pick from 'ramda/src/pick'
import renderHelp from 'render-help'
import { handler as list, type ListCommandOptions } from './list'
import { handler as list, type ListCommandOptions, EXCLUDE_PEERS_HELP } from './list'
export function rcOptionsTypes (): Record<string, unknown> {
return pick([
@@ -23,6 +23,7 @@ export function rcOptionsTypes (): Record<string, unknown> {
export const cliOptionsTypes = (): Record<string, unknown> => ({
...rcOptionsTypes(),
'exclude-peers': Boolean,
recursive: Boolean,
})
@@ -84,6 +85,7 @@ For options that may be used with `-r`, see "pnpm help recursive"',
name: '--depth <number>',
description: 'Max display depth of the dependency graph',
},
EXCLUDE_PEERS_HELP,
OPTIONS.globalDir,
...UNIVERSAL_OPTIONS,
],