mirror of
https://github.com/pnpm/pnpm.git
synced 2026-07-26 07:27:20 -04:00
feat: add an option to list and why to exclude peer dependencies from the output (#8506)
This commit is contained in:
8
.changeset/odd-parrots-refuse.md
Normal file
8
.changeset/odd-parrots-refuse.md
Normal 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).
|
||||||
@@ -34,6 +34,7 @@ export async function buildDependenciesHierarchy (
|
|||||||
projectPaths: string[] | undefined,
|
projectPaths: string[] | undefined,
|
||||||
maybeOpts: {
|
maybeOpts: {
|
||||||
depth: number
|
depth: number
|
||||||
|
excludePeerDependencies?: boolean
|
||||||
include?: { [dependenciesField in DependenciesField]: boolean }
|
include?: { [dependenciesField in DependenciesField]: boolean }
|
||||||
registries?: Registries
|
registries?: Registries
|
||||||
onlyProjects?: boolean
|
onlyProjects?: boolean
|
||||||
@@ -70,6 +71,7 @@ export async function buildDependenciesHierarchy (
|
|||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
depth: maybeOpts.depth || 0,
|
depth: maybeOpts.depth || 0,
|
||||||
|
excludePeerDependencies: maybeOpts.excludePeerDependencies,
|
||||||
include: maybeOpts.include ?? {
|
include: maybeOpts.include ?? {
|
||||||
dependencies: true,
|
dependencies: true,
|
||||||
devDependencies: true,
|
devDependencies: true,
|
||||||
@@ -103,6 +105,7 @@ async function dependenciesHierarchyForPackage (
|
|||||||
wantedLockfile: Lockfile | null,
|
wantedLockfile: Lockfile | null,
|
||||||
opts: {
|
opts: {
|
||||||
depth: number
|
depth: number
|
||||||
|
excludePeerDependencies?: boolean
|
||||||
include: { [dependenciesField in DependenciesField]: boolean }
|
include: { [dependenciesField in DependenciesField]: boolean }
|
||||||
registries: Registries
|
registries: Registries
|
||||||
onlyProjects?: boolean
|
onlyProjects?: boolean
|
||||||
@@ -127,6 +130,7 @@ async function dependenciesHierarchyForPackage (
|
|||||||
const depTypes = detectDepTypes(currentLockfile)
|
const depTypes = detectDepTypes(currentLockfile)
|
||||||
const getChildrenTree = getTree.bind(null, {
|
const getChildrenTree = getTree.bind(null, {
|
||||||
currentPackages: currentLockfile.packages ?? {},
|
currentPackages: currentLockfile.packages ?? {},
|
||||||
|
excludePeerDependencies: opts.excludePeerDependencies,
|
||||||
importers: currentLockfile.importers,
|
importers: currentLockfile.importers,
|
||||||
includeOptionalDependencies: opts.include.optionalDependencies,
|
includeOptionalDependencies: opts.include.optionalDependencies,
|
||||||
depTypes,
|
depTypes,
|
||||||
@@ -134,7 +138,6 @@ async function dependenciesHierarchyForPackage (
|
|||||||
onlyProjects: opts.onlyProjects,
|
onlyProjects: opts.onlyProjects,
|
||||||
rewriteLinkVersionDir: projectPath,
|
rewriteLinkVersionDir: projectPath,
|
||||||
maxDepth: opts.depth,
|
maxDepth: opts.depth,
|
||||||
modulesDir,
|
|
||||||
registries: opts.registries,
|
registries: opts.registries,
|
||||||
search: opts.search,
|
search: opts.search,
|
||||||
skipped: opts.skipped,
|
skipped: opts.skipped,
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ interface GetTreeOpts {
|
|||||||
maxDepth: number
|
maxDepth: number
|
||||||
rewriteLinkVersionDir: string
|
rewriteLinkVersionDir: string
|
||||||
includeOptionalDependencies: boolean
|
includeOptionalDependencies: boolean
|
||||||
|
excludePeerDependencies?: boolean
|
||||||
lockfileDir: string
|
lockfileDir: string
|
||||||
onlyProjects?: boolean
|
onlyProjects?: boolean
|
||||||
search?: SearchFunction
|
search?: SearchFunction
|
||||||
@@ -209,7 +210,9 @@ function getTreeHelper (
|
|||||||
if (matchedSearched) {
|
if (matchedSearched) {
|
||||||
newEntry.searched = true
|
newEntry.searched = true
|
||||||
}
|
}
|
||||||
resultDependencies.push(newEntry)
|
if (!newEntry.isPeer || !opts.excludePeerDependencies || newEntry.dependencies?.length) {
|
||||||
|
resultDependencies.push(newEntry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -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 }),
|
||||||
|
])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ export async function searchForPackages (
|
|||||||
projectPaths: string[],
|
projectPaths: string[],
|
||||||
opts: {
|
opts: {
|
||||||
depth: number
|
depth: number
|
||||||
|
excludePeerDependencies?: boolean
|
||||||
lockfileDir: string
|
lockfileDir: string
|
||||||
include?: { [dependenciesField in DependenciesField]: boolean }
|
include?: { [dependenciesField in DependenciesField]: boolean }
|
||||||
onlyProjects?: boolean
|
onlyProjects?: boolean
|
||||||
@@ -72,6 +73,7 @@ export async function searchForPackages (
|
|||||||
return Promise.all(
|
return Promise.all(
|
||||||
Object.entries(await buildDependenciesHierarchy(projectPaths, {
|
Object.entries(await buildDependenciesHierarchy(projectPaths, {
|
||||||
depth: opts.depth,
|
depth: opts.depth,
|
||||||
|
excludePeerDependencies: opts.excludePeerDependencies,
|
||||||
include: opts.include,
|
include: opts.include,
|
||||||
lockfileDir: opts.lockfileDir,
|
lockfileDir: opts.lockfileDir,
|
||||||
onlyProjects: opts.onlyProjects,
|
onlyProjects: opts.onlyProjects,
|
||||||
@@ -130,6 +132,7 @@ export async function list (
|
|||||||
maybeOpts: {
|
maybeOpts: {
|
||||||
alwaysPrintRootPackage?: boolean
|
alwaysPrintRootPackage?: boolean
|
||||||
depth?: number
|
depth?: number
|
||||||
|
excludePeerDependencies?: boolean
|
||||||
lockfileDir: string
|
lockfileDir: string
|
||||||
long?: boolean
|
long?: boolean
|
||||||
include?: { [dependenciesField in DependenciesField]: boolean }
|
include?: { [dependenciesField in DependenciesField]: boolean }
|
||||||
@@ -152,6 +155,7 @@ export async function list (
|
|||||||
}, {} as Record<string, DependenciesHierarchy>)
|
}, {} as Record<string, DependenciesHierarchy>)
|
||||||
: await buildDependenciesHierarchy(projectPaths, {
|
: await buildDependenciesHierarchy(projectPaths, {
|
||||||
depth: opts.depth,
|
depth: opts.depth,
|
||||||
|
excludePeerDependencies: maybeOpts?.excludePeerDependencies,
|
||||||
include: maybeOpts?.include,
|
include: maybeOpts?.include,
|
||||||
lockfileDir: maybeOpts?.lockfileDir,
|
lockfileDir: maybeOpts?.lockfileDir,
|
||||||
onlyProjects: maybeOpts?.onlyProjects,
|
onlyProjects: maybeOpts?.onlyProjects,
|
||||||
|
|||||||
@@ -7,6 +7,11 @@ import pick from 'ramda/src/pick'
|
|||||||
import renderHelp from 'render-help'
|
import renderHelp from 'render-help'
|
||||||
import { listRecursive } from './recursive'
|
import { listRecursive } from './recursive'
|
||||||
|
|
||||||
|
export const EXCLUDE_PEERS_HELP = {
|
||||||
|
description: 'Exclude peer dependencies',
|
||||||
|
name: '--exclude-peers',
|
||||||
|
}
|
||||||
|
|
||||||
export function rcOptionsTypes (): Record<string, unknown> {
|
export function rcOptionsTypes (): Record<string, unknown> {
|
||||||
return pick([
|
return pick([
|
||||||
'depth',
|
'depth',
|
||||||
@@ -24,6 +29,7 @@ export function rcOptionsTypes (): Record<string, unknown> {
|
|||||||
|
|
||||||
export const cliOptionsTypes = (): Record<string, unknown> => ({
|
export const cliOptionsTypes = (): Record<string, unknown> => ({
|
||||||
...rcOptionsTypes(),
|
...rcOptionsTypes(),
|
||||||
|
'exclude-peers': Boolean,
|
||||||
'only-projects': Boolean,
|
'only-projects': Boolean,
|
||||||
recursive: 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`",
|
description: "Don't display packages from `optionalDependencies`",
|
||||||
name: '--no-optional',
|
name: '--no-optional',
|
||||||
},
|
},
|
||||||
|
EXCLUDE_PEERS_HELP,
|
||||||
OPTIONS.globalDir,
|
OPTIONS.globalDir,
|
||||||
...UNIVERSAL_OPTIONS,
|
...UNIVERSAL_OPTIONS,
|
||||||
],
|
],
|
||||||
@@ -125,6 +132,7 @@ export type ListCommandOptions = Pick<Config,
|
|||||||
> & Partial<Pick<Config, 'cliOptions'>> & {
|
> & Partial<Pick<Config, 'cliOptions'>> & {
|
||||||
alwaysPrintRootPackage?: boolean
|
alwaysPrintRootPackage?: boolean
|
||||||
depth?: number
|
depth?: number
|
||||||
|
excludePeers?: boolean
|
||||||
lockfileDir?: string
|
lockfileDir?: string
|
||||||
long?: boolean
|
long?: boolean
|
||||||
parseable?: boolean
|
parseable?: boolean
|
||||||
@@ -160,6 +168,7 @@ export async function render (
|
|||||||
opts: {
|
opts: {
|
||||||
alwaysPrintRootPackage?: boolean
|
alwaysPrintRootPackage?: boolean
|
||||||
depth?: number
|
depth?: number
|
||||||
|
excludePeers?: boolean
|
||||||
include: IncludedDependencies
|
include: IncludedDependencies
|
||||||
lockfileDir: string
|
lockfileDir: string
|
||||||
long?: boolean
|
long?: boolean
|
||||||
@@ -173,6 +182,7 @@ export async function render (
|
|||||||
const listOpts = {
|
const listOpts = {
|
||||||
alwaysPrintRootPackage: opts.alwaysPrintRootPackage,
|
alwaysPrintRootPackage: opts.alwaysPrintRootPackage,
|
||||||
depth: opts.depth ?? 0,
|
depth: opts.depth ?? 0,
|
||||||
|
excludePeerDependencies: opts.excludePeers,
|
||||||
include: opts.include,
|
include: opts.include,
|
||||||
lockfileDir: opts.lockfileDir,
|
lockfileDir: opts.lockfileDir,
|
||||||
long: opts.long,
|
long: opts.long,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { types as allTypes } from '@pnpm/config'
|
|||||||
import { PnpmError } from '@pnpm/error'
|
import { PnpmError } from '@pnpm/error'
|
||||||
import pick from 'ramda/src/pick'
|
import pick from 'ramda/src/pick'
|
||||||
import renderHelp from 'render-help'
|
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> {
|
export function rcOptionsTypes (): Record<string, unknown> {
|
||||||
return pick([
|
return pick([
|
||||||
@@ -23,6 +23,7 @@ export function rcOptionsTypes (): Record<string, unknown> {
|
|||||||
|
|
||||||
export const cliOptionsTypes = (): Record<string, unknown> => ({
|
export const cliOptionsTypes = (): Record<string, unknown> => ({
|
||||||
...rcOptionsTypes(),
|
...rcOptionsTypes(),
|
||||||
|
'exclude-peers': Boolean,
|
||||||
recursive: Boolean,
|
recursive: Boolean,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -84,6 +85,7 @@ For options that may be used with `-r`, see "pnpm help recursive"',
|
|||||||
name: '--depth <number>',
|
name: '--depth <number>',
|
||||||
description: 'Max display depth of the dependency graph',
|
description: 'Max display depth of the dependency graph',
|
||||||
},
|
},
|
||||||
|
EXCLUDE_PEERS_HELP,
|
||||||
OPTIONS.globalDir,
|
OPTIONS.globalDir,
|
||||||
...UNIVERSAL_OPTIONS,
|
...UNIVERSAL_OPTIONS,
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user