diff --git a/.changeset/odd-parrots-refuse.md b/.changeset/odd-parrots-refuse.md new file mode 100644 index 0000000000..df44f5c5fb --- /dev/null +++ b/.changeset/odd-parrots-refuse.md @@ -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). diff --git a/reviewing/dependencies-hierarchy/src/buildDependenciesHierarchy.ts b/reviewing/dependencies-hierarchy/src/buildDependenciesHierarchy.ts index 29c4b9da50..68b483997d 100644 --- a/reviewing/dependencies-hierarchy/src/buildDependenciesHierarchy.ts +++ b/reviewing/dependencies-hierarchy/src/buildDependenciesHierarchy.ts @@ -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, diff --git a/reviewing/dependencies-hierarchy/src/getTree.ts b/reviewing/dependencies-hierarchy/src/getTree.ts index 8719dd0ef1..00dfd2a69d 100644 --- a/reviewing/dependencies-hierarchy/src/getTree.ts +++ b/reviewing/dependencies-hierarchy/src/getTree.ts @@ -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) + } } }) diff --git a/reviewing/dependencies-hierarchy/test/getTree.test.ts b/reviewing/dependencies-hierarchy/test/getTree.test.ts index 3ba3e612e0..ccdf57f03f 100644 --- a/reviewing/dependencies-hierarchy/test/getTree.test.ts +++ b/reviewing/dependencies-hierarchy/test/getTree.test.ts @@ -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(), + 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 }), + ]) + }) }) diff --git a/reviewing/list/src/index.ts b/reviewing/list/src/index.ts index 6c7a7f4a24..375a5ac3fe 100644 --- a/reviewing/list/src/index.ts +++ b/reviewing/list/src/index.ts @@ -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) : await buildDependenciesHierarchy(projectPaths, { depth: opts.depth, + excludePeerDependencies: maybeOpts?.excludePeerDependencies, include: maybeOpts?.include, lockfileDir: maybeOpts?.lockfileDir, onlyProjects: maybeOpts?.onlyProjects, diff --git a/reviewing/plugin-commands-listing/src/list.ts b/reviewing/plugin-commands-listing/src/list.ts index a808420241..2750fcae67 100644 --- a/reviewing/plugin-commands-listing/src/list.ts +++ b/reviewing/plugin-commands-listing/src/list.ts @@ -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 { return pick([ 'depth', @@ -24,6 +29,7 @@ export function rcOptionsTypes (): Record { export const cliOptionsTypes = (): Record => ({ ...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 & Partial> & { 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, diff --git a/reviewing/plugin-commands-listing/src/why.ts b/reviewing/plugin-commands-listing/src/why.ts index f70bacfcf7..c0f77da8bb 100644 --- a/reviewing/plugin-commands-listing/src/why.ts +++ b/reviewing/plugin-commands-listing/src/why.ts @@ -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 { return pick([ @@ -23,6 +23,7 @@ export function rcOptionsTypes (): Record { export const cliOptionsTypes = (): Record => ({ ...rcOptionsTypes(), + 'exclude-peers': Boolean, recursive: Boolean, }) @@ -84,6 +85,7 @@ For options that may be used with `-r`, see "pnpm help recursive"', name: '--depth ', description: 'Max display depth of the dependency graph', }, + EXCLUDE_PEERS_HELP, OPTIONS.globalDir, ...UNIVERSAL_OPTIONS, ],