mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-24 07:38:12 -05:00
fix: peer dependency rules should not change the lockfile (#7758)
* fix: peer dependency rules should not change the lockfile * test: fix * fix: hide peer issues warning if there nothing to report
This commit is contained in:
9
.changeset/cyan-humans-report.md
Normal file
9
.changeset/cyan-humans-report.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
"@pnpm/hooks.read-package-hook": major
|
||||
"@pnpm/core": major
|
||||
"@pnpm/render-peer-issues": minor
|
||||
"@pnpm/default-reporter": minor
|
||||
"pnpm": minor
|
||||
---
|
||||
|
||||
Peer dependency rules should only affect reporting, not data in the lockfile.
|
||||
@@ -10,6 +10,7 @@ import { reporterForClient } from './reporterForClient'
|
||||
import { formatWarn } from './reporterForClient/utils/formatWarn'
|
||||
import { reporterForServer } from './reporterForServer'
|
||||
import { type FilterPkgsDiff } from './reporterForClient/reportSummary'
|
||||
import { type PeerDependencyRules } from '@pnpm/types'
|
||||
|
||||
export { formatWarn }
|
||||
|
||||
@@ -28,6 +29,7 @@ export function initDefaultReporter (
|
||||
hideProgressPrefix?: boolean
|
||||
hideLifecycleOutput?: boolean
|
||||
hideLifecyclePrefix?: boolean
|
||||
peerDependencyRules?: PeerDependencyRules
|
||||
}
|
||||
context: {
|
||||
argv: string[]
|
||||
@@ -104,6 +106,7 @@ export function toOutput$ (
|
||||
appendOnly?: boolean
|
||||
logLevel?: LogLevel
|
||||
outputMaxWidth?: number
|
||||
peerDependencyRules?: PeerDependencyRules
|
||||
streamLifecycleOutput?: boolean
|
||||
aggregateOutput?: boolean
|
||||
throttleProgress?: number
|
||||
@@ -260,6 +263,7 @@ export function toOutput$ (
|
||||
config: opts.context.config,
|
||||
env: opts.context.env ?? process.env,
|
||||
filterPkgsDiff: opts.filterPkgsDiff,
|
||||
peerDependencyRules: opts.reportingOptions?.peerDependencyRules,
|
||||
process: opts.context.process ?? process,
|
||||
isRecursive: opts.context.config?.['recursive'] === true,
|
||||
logLevel: opts.reportingOptions?.logLevel,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { renderDedupeCheckIssues } from '@pnpm/dedupe.issues-renderer'
|
||||
import { type DedupeCheckIssues } from '@pnpm/dedupe.types'
|
||||
import { type PnpmError } from '@pnpm/error'
|
||||
import { renderPeerIssues } from '@pnpm/render-peer-issues'
|
||||
import { type PeerDependencyIssuesByProjects } from '@pnpm/types'
|
||||
import { type PeerDependencyRules, type PeerDependencyIssuesByProjects } from '@pnpm/types'
|
||||
import chalk from 'chalk'
|
||||
import equals from 'ramda/src/equals'
|
||||
import StackTracey from 'stacktracey'
|
||||
@@ -19,8 +19,9 @@ StackTracey.maxColumnWidths = {
|
||||
const highlight = chalk.yellow
|
||||
const colorPath = chalk.gray
|
||||
|
||||
export function reportError (logObj: Log, config?: Config) {
|
||||
const errorInfo = getErrorInfo(logObj, config)
|
||||
export function reportError (logObj: Log, config?: Config, peerDependencyRules?: PeerDependencyRules) {
|
||||
const errorInfo = getErrorInfo(logObj, config, peerDependencyRules)
|
||||
if (!errorInfo) return null
|
||||
let output = formatErrorSummary(errorInfo.title, (logObj as LogObjWithPossibleError).err?.code)
|
||||
if (logObj['pkgsStack'] != null) {
|
||||
if (logObj['pkgsStack'].length > 0) {
|
||||
@@ -43,10 +44,10 @@ export function reportError (logObj: Log, config?: Config) {
|
||||
}
|
||||
}
|
||||
|
||||
function getErrorInfo (logObj: Log, config?: Config): {
|
||||
function getErrorInfo (logObj: Log, config?: Config, peerDependencyRules?: PeerDependencyRules): {
|
||||
title: string
|
||||
body?: string
|
||||
} {
|
||||
} | null {
|
||||
if (logObj['err']) {
|
||||
const err = logObj['err'] as (PnpmError & { stack: object })
|
||||
switch (err.code) {
|
||||
@@ -75,7 +76,7 @@ function getErrorInfo (logObj: Log, config?: Config): {
|
||||
case 'ERR_PNPM_UNSUPPORTED_ENGINE':
|
||||
return reportEngineError(logObj as any) // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
case 'ERR_PNPM_PEER_DEP_ISSUES':
|
||||
return reportPeerDependencyIssuesError(err, logObj as any) // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
return reportPeerDependencyIssuesError(err, logObj as any, peerDependencyRules) // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
case 'ERR_PNPM_DEDUPE_CHECK_ISSUES':
|
||||
return reportDedupeCheckIssuesError(err, logObj as any) // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
case 'ERR_PNPM_FETCH_401':
|
||||
@@ -405,7 +406,8 @@ function hideSecureInfo (key: string, value: string) {
|
||||
|
||||
function reportPeerDependencyIssuesError (
|
||||
err: Error,
|
||||
msg: { issuesByProjects: PeerDependencyIssuesByProjects }
|
||||
msg: { issuesByProjects: PeerDependencyIssuesByProjects },
|
||||
peerDependencyRules?: PeerDependencyRules
|
||||
) {
|
||||
const hasMissingPeers = getHasMissingPeers(msg.issuesByProjects)
|
||||
const hints: string[] = []
|
||||
@@ -413,9 +415,11 @@ function reportPeerDependencyIssuesError (
|
||||
hints.push('If you want peer dependencies to be automatically installed, add "auto-install-peers=true" to an .npmrc file at the root of your project.')
|
||||
}
|
||||
hints.push('If you don\'t want pnpm to fail on peer dependency issues, add "strict-peer-dependencies=false" to an .npmrc file at the root of your project.')
|
||||
const rendered = renderPeerIssues(msg.issuesByProjects, { rules: peerDependencyRules })
|
||||
if (!rendered) return null
|
||||
return {
|
||||
title: err.message,
|
||||
body: `${renderPeerIssues(msg.issuesByProjects)}
|
||||
body: `${rendered}
|
||||
${hints.map((hint) => `hint: ${hint}`).join('\n')}
|
||||
`,
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import { reportSkippedOptionalDependencies } from './reportSkippedOptionalDepend
|
||||
import { reportStats } from './reportStats'
|
||||
import { reportSummary, type FilterPkgsDiff } from './reportSummary'
|
||||
import { reportUpdateCheck } from './reportUpdateCheck'
|
||||
import { type PeerDependencyRules } from '@pnpm/types'
|
||||
|
||||
const PRINT_EXECUTION_TIME_IN_COMMANDS = {
|
||||
install: true,
|
||||
@@ -58,6 +59,7 @@ export function reporterForClient (
|
||||
config?: Config
|
||||
env: NodeJS.ProcessEnv
|
||||
filterPkgsDiff?: FilterPkgsDiff
|
||||
peerDependencyRules?: PeerDependencyRules
|
||||
process: NodeJS.Process
|
||||
isRecursive: boolean
|
||||
logLevel?: LogLevel
|
||||
@@ -94,6 +96,7 @@ export function reporterForClient (
|
||||
cwd,
|
||||
logLevel: opts.logLevel,
|
||||
zoomOutCurrent: opts.isRecursive,
|
||||
peerDependencyRules: opts.peerDependencyRules,
|
||||
}
|
||||
),
|
||||
reportInstallChecks(log$.installCheck, { cwd }),
|
||||
@@ -116,7 +119,7 @@ export function reporterForClient (
|
||||
|
||||
if (logLevelNumber >= LOG_LEVEL_NUMBER.warn) {
|
||||
outputs.push(
|
||||
reportPeerDependencyIssues(log$),
|
||||
reportPeerDependencyIssues(log$, opts.peerDependencyRules),
|
||||
reportDeprecations({
|
||||
deprecation: log$.deprecation,
|
||||
stage: log$.stage,
|
||||
|
||||
@@ -7,6 +7,7 @@ import { filter, map } from 'rxjs/operators'
|
||||
import { reportError } from '../reportError'
|
||||
import { formatWarn } from './utils/formatWarn'
|
||||
import { autozoom } from './utils/zooming'
|
||||
import { type PeerDependencyRules } from '@pnpm/types'
|
||||
|
||||
// eslint-disable:object-literal-sort-keys
|
||||
export const LOG_LEVEL_NUMBER: Record<LogLevel, number> = {
|
||||
@@ -30,6 +31,7 @@ export function reportMisc (
|
||||
logLevel?: LogLevel
|
||||
config?: Config
|
||||
zoomOutCurrent: boolean
|
||||
peerDependencyRules?: PeerDependencyRules
|
||||
}
|
||||
) {
|
||||
const maxLogLevel = LOG_LEVEL_NUMBER[opts.logLevel ?? 'info'] ?? LOG_LEVEL_NUMBER['info']
|
||||
@@ -42,13 +44,16 @@ export function reportMisc (
|
||||
case 'warn': {
|
||||
return reportWarning(obj)
|
||||
}
|
||||
case 'error':
|
||||
case 'error': {
|
||||
const errorOutput = reportError(obj, opts.config, opts.peerDependencyRules)
|
||||
if (!errorOutput) return Rx.NEVER
|
||||
if (obj['prefix'] && obj['prefix'] !== opts.cwd) {
|
||||
return Rx.of({
|
||||
msg: `${obj['prefix'] as string}:` + os.EOL + reportError(obj, opts.config),
|
||||
msg: `${obj['prefix'] as string}:` + os.EOL + errorOutput,
|
||||
})
|
||||
}
|
||||
return Rx.of({ msg: reportError(obj, opts.config) })
|
||||
return Rx.of({ msg: errorOutput })
|
||||
}
|
||||
default:
|
||||
return Rx.of({ msg: obj['message'] })
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { type PeerDependencyIssuesLog } from '@pnpm/core-loggers'
|
||||
import { renderPeerIssues } from '@pnpm/render-peer-issues'
|
||||
import { type PeerDependencyRules } from '@pnpm/types'
|
||||
import * as Rx from 'rxjs'
|
||||
import { map, take } from 'rxjs/operators'
|
||||
import { formatWarn } from './utils/formatWarn'
|
||||
@@ -7,12 +8,21 @@ import { formatWarn } from './utils/formatWarn'
|
||||
export function reportPeerDependencyIssues (
|
||||
log$: {
|
||||
peerDependencyIssues: Rx.Observable<PeerDependencyIssuesLog>
|
||||
}
|
||||
},
|
||||
peerDependencyRules?: PeerDependencyRules
|
||||
) {
|
||||
return log$.peerDependencyIssues.pipe(
|
||||
take(1),
|
||||
map((log) => Rx.of({
|
||||
msg: `${formatWarn('Issues with peer dependencies found')}\n${renderPeerIssues(log.issuesByProjects)}`,
|
||||
}))
|
||||
map((log) => {
|
||||
const renderedPeerIssues = renderPeerIssues(log.issuesByProjects, {
|
||||
rules: peerDependencyRules,
|
||||
})
|
||||
if (!renderedPeerIssues) {
|
||||
return Rx.NEVER
|
||||
}
|
||||
return Rx.of({
|
||||
msg: `${formatWarn('Issues with peer dependencies found')}\n${renderedPeerIssues}`,
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
import semver from 'semver'
|
||||
import isEmpty from 'ramda/src/isEmpty'
|
||||
import { type PeerDependencyRules, type ReadPackageHook, type PackageManifest, type ProjectManifest } from '@pnpm/types'
|
||||
import { PnpmError } from '@pnpm/error'
|
||||
import { parseOverrides, type VersionOverride } from '@pnpm/parse-overrides'
|
||||
import { createMatcher } from '@pnpm/matcher'
|
||||
import { isSubRange } from './isSubRange'
|
||||
|
||||
export function createPeerDependencyPatcher (
|
||||
peerDependencyRules: PeerDependencyRules
|
||||
): ReadPackageHook {
|
||||
const ignoreMissingPatterns = [...new Set(peerDependencyRules.ignoreMissing ?? [])]
|
||||
const ignoreMissingMatcher = createMatcher(ignoreMissingPatterns)
|
||||
const allowAnyPatterns = [...new Set(peerDependencyRules.allowAny ?? [])]
|
||||
const allowAnyMatcher = createMatcher(allowAnyPatterns)
|
||||
const { allowedVersionsMatchAll, allowedVersionsByParentPkgName } = parseAllowedVersions(peerDependencyRules.allowedVersions ?? {})
|
||||
const _getAllowedVersionsByParentPkg = getAllowedVersionsByParentPkg.bind(null, allowedVersionsByParentPkgName)
|
||||
|
||||
return (pkg) => {
|
||||
if (isEmpty(pkg.peerDependencies)) return pkg
|
||||
const allowedVersions = {
|
||||
...allowedVersionsMatchAll,
|
||||
..._getAllowedVersionsByParentPkg(pkg),
|
||||
}
|
||||
for (const [peerName, peerVersion] of Object.entries(pkg.peerDependencies ?? {})) {
|
||||
if (
|
||||
ignoreMissingMatcher(peerName) &&
|
||||
!pkg.peerDependenciesMeta?.[peerName]?.optional
|
||||
) {
|
||||
pkg.peerDependenciesMeta = pkg.peerDependenciesMeta ?? {}
|
||||
pkg.peerDependenciesMeta[peerName] = {
|
||||
optional: true,
|
||||
}
|
||||
}
|
||||
if (allowAnyMatcher(peerName)) {
|
||||
pkg.peerDependencies![peerName] = '*'
|
||||
continue
|
||||
}
|
||||
if (!allowedVersions?.[peerName] || peerVersion === '*') {
|
||||
continue
|
||||
}
|
||||
if (allowedVersions?.[peerName].includes('*')) {
|
||||
pkg.peerDependencies![peerName] = '*'
|
||||
continue
|
||||
}
|
||||
const currentVersions = parseVersions(pkg.peerDependencies![peerName])
|
||||
|
||||
allowedVersions[peerName].forEach(allowedVersion => {
|
||||
if (!currentVersions.includes(allowedVersion)) {
|
||||
currentVersions.push(allowedVersion)
|
||||
}
|
||||
})
|
||||
|
||||
pkg.peerDependencies![peerName] = currentVersions.join(' || ')
|
||||
}
|
||||
return pkg
|
||||
}
|
||||
}
|
||||
|
||||
type AllowedVersionsByParentPkgName = Record<string, Array<Required<Pick<VersionOverride, 'parentPkg' | 'targetPkg'>> & { ranges: string[] }>>
|
||||
|
||||
function parseAllowedVersions (allowedVersions: Record<string, string>) {
|
||||
const overrides = tryParseAllowedVersions(allowedVersions)
|
||||
const allowedVersionsMatchAll: Record<string, string[]> = {}
|
||||
const allowedVersionsByParentPkgName: AllowedVersionsByParentPkgName = {}
|
||||
for (const { parentPkg, targetPkg, newPref } of overrides) {
|
||||
const ranges = parseVersions(newPref)
|
||||
if (!parentPkg) {
|
||||
allowedVersionsMatchAll[targetPkg.name] = ranges
|
||||
continue
|
||||
}
|
||||
if (!allowedVersionsByParentPkgName[parentPkg.name]) {
|
||||
allowedVersionsByParentPkgName[parentPkg.name] = []
|
||||
}
|
||||
allowedVersionsByParentPkgName[parentPkg.name].push({
|
||||
parentPkg,
|
||||
targetPkg,
|
||||
ranges,
|
||||
})
|
||||
}
|
||||
return {
|
||||
allowedVersionsMatchAll,
|
||||
allowedVersionsByParentPkgName,
|
||||
}
|
||||
}
|
||||
|
||||
function tryParseAllowedVersions (allowedVersions: Record<string, string>): VersionOverride[] {
|
||||
try {
|
||||
return parseOverrides(allowedVersions ?? {})
|
||||
} catch (err) {
|
||||
throw new PnpmError('INVALID_ALLOWED_VERSION_SELECTOR',
|
||||
`${(err as PnpmError).message} in pnpm.peerDependencyRules.allowedVersions`)
|
||||
}
|
||||
}
|
||||
|
||||
function getAllowedVersionsByParentPkg (
|
||||
allowedVersionsByParentPkgName: AllowedVersionsByParentPkgName,
|
||||
pkg: PackageManifest | ProjectManifest
|
||||
): Record<string, string[]> {
|
||||
if (!pkg.name || !allowedVersionsByParentPkgName[pkg.name]) return {}
|
||||
|
||||
return allowedVersionsByParentPkgName[pkg.name]
|
||||
.reduce((acc, { targetPkg, parentPkg, ranges }) => {
|
||||
if (!pkg.peerDependencies![targetPkg.name]) return acc
|
||||
if (!parentPkg.pref || pkg.version &&
|
||||
(isSubRange(parentPkg.pref, pkg.version) || semver.satisfies(pkg.version, parentPkg.pref))) {
|
||||
acc[targetPkg.name] = ranges
|
||||
}
|
||||
return acc
|
||||
}, {} as Record<string, string[]>)
|
||||
}
|
||||
|
||||
function parseVersions (versions: string): string[] {
|
||||
return versions.split('||').map(v => v.trim())
|
||||
}
|
||||
@@ -2,7 +2,6 @@ import { packageExtensions as compatPackageExtensions } from '@yarnpkg/extension
|
||||
import {
|
||||
type PackageExtension,
|
||||
type PackageManifest,
|
||||
type PeerDependencyRules,
|
||||
type ProjectManifest,
|
||||
type ReadPackageHook,
|
||||
} from '@pnpm/types'
|
||||
@@ -11,7 +10,6 @@ import pipeWith from 'ramda/src/pipeWith'
|
||||
import { createOptionalDependenciesRemover } from './createOptionalDependenciesRemover'
|
||||
import { createPackageExtender } from './createPackageExtender'
|
||||
import { createVersionsOverrider } from './createVersionsOverrider'
|
||||
import { createPeerDependencyPatcher } from './createPeerDependencyPatcher'
|
||||
|
||||
export function createReadPackageHook (
|
||||
{
|
||||
@@ -20,7 +18,6 @@ export function createReadPackageHook (
|
||||
overrides,
|
||||
ignoredOptionalDependencies,
|
||||
packageExtensions,
|
||||
peerDependencyRules,
|
||||
readPackageHook,
|
||||
}: {
|
||||
ignoreCompatibilityDb?: boolean
|
||||
@@ -28,7 +25,6 @@ export function createReadPackageHook (
|
||||
overrides?: Record<string, string>
|
||||
ignoredOptionalDependencies?: string[]
|
||||
packageExtensions?: Record<string, PackageExtension>
|
||||
peerDependencyRules?: PeerDependencyRules
|
||||
readPackageHook?: ReadPackageHook[] | ReadPackageHook
|
||||
}
|
||||
): ReadPackageHook | undefined {
|
||||
@@ -50,16 +46,6 @@ export function createReadPackageHook (
|
||||
if (ignoredOptionalDependencies && !isEmpty(ignoredOptionalDependencies)) {
|
||||
hooks.push(createOptionalDependenciesRemover(ignoredOptionalDependencies))
|
||||
}
|
||||
if (
|
||||
peerDependencyRules != null &&
|
||||
(
|
||||
!isEmpty(peerDependencyRules.ignoreMissing) ||
|
||||
!isEmpty(peerDependencyRules.allowedVersions) ||
|
||||
!isEmpty(peerDependencyRules.allowAny)
|
||||
)
|
||||
) {
|
||||
hooks.push(createPeerDependencyPatcher(peerDependencyRules))
|
||||
}
|
||||
|
||||
if (hooks.length === 0) {
|
||||
return undefined
|
||||
|
||||
@@ -1,196 +0,0 @@
|
||||
import { type ProjectManifest } from '@pnpm/types'
|
||||
import { createPeerDependencyPatcher } from '../lib/createPeerDependencyPatcher'
|
||||
|
||||
test('createPeerDependencyPatcher() ignores missing', () => {
|
||||
const patcher = createPeerDependencyPatcher({
|
||||
ignoreMissing: ['foo'],
|
||||
})
|
||||
const patchedPkg = patcher({
|
||||
peerDependencies: {
|
||||
foo: '*',
|
||||
bar: '*',
|
||||
},
|
||||
}) as ProjectManifest
|
||||
expect(patchedPkg.peerDependenciesMeta).toStrictEqual({
|
||||
foo: {
|
||||
optional: true,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('createPeerDependencyPatcher() pattern matches to ignore missing', () => {
|
||||
const patcher = createPeerDependencyPatcher({
|
||||
ignoreMissing: ['f*r'],
|
||||
})
|
||||
const patchedPkg = patcher({
|
||||
peerDependencies: {
|
||||
foobar: '*',
|
||||
bar: '*',
|
||||
},
|
||||
}) as ProjectManifest
|
||||
expect(patchedPkg.peerDependenciesMeta).toStrictEqual({
|
||||
foobar: {
|
||||
optional: true,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('createPeerDependencyPatcher() extends peer ranges', () => {
|
||||
const patcher = createPeerDependencyPatcher({
|
||||
allowedVersions: {
|
||||
foo: '1',
|
||||
qar: '1',
|
||||
baz: '*',
|
||||
},
|
||||
})
|
||||
const patchedPkg = patcher({
|
||||
peerDependencies: {
|
||||
foo: '0',
|
||||
bar: '0',
|
||||
qar: '*',
|
||||
baz: '1',
|
||||
},
|
||||
}) as ProjectManifest
|
||||
expect(patchedPkg.peerDependencies).toStrictEqual({
|
||||
foo: '0 || 1',
|
||||
bar: '0',
|
||||
qar: '*',
|
||||
baz: '*',
|
||||
})
|
||||
})
|
||||
|
||||
test('createPeerDependencyPatcher() ignores peer versions from allowAny', () => {
|
||||
const patcher = createPeerDependencyPatcher({
|
||||
allowAny: ['foo', 'bar'],
|
||||
})
|
||||
const patchedPkg = patcher({
|
||||
peerDependencies: {
|
||||
foo: '2',
|
||||
bar: '2',
|
||||
qar: '2',
|
||||
baz: '2',
|
||||
},
|
||||
}) as ProjectManifest
|
||||
expect(patchedPkg.peerDependencies).toStrictEqual({
|
||||
foo: '*',
|
||||
bar: '*',
|
||||
qar: '2',
|
||||
baz: '2',
|
||||
})
|
||||
})
|
||||
|
||||
test('createPeerDependencyPatcher() does not create duplicate extended ranges', async () => {
|
||||
const patcher = createPeerDependencyPatcher({
|
||||
allowedVersions: {
|
||||
foo: '1',
|
||||
same: '12',
|
||||
multi: '16',
|
||||
mix: '1 || 2 || 3',
|
||||
partialmatch: '1',
|
||||
nopadding: '^17.0.1||18.x',
|
||||
},
|
||||
})
|
||||
const patchedPkg = patcher({
|
||||
peerDependencies: {
|
||||
foo: '0',
|
||||
same: '12',
|
||||
multi: '16 || 17',
|
||||
mix: '1 || 4',
|
||||
partialmatch: '16 || 1.2.1',
|
||||
nopadding: '15.0.1||16',
|
||||
},
|
||||
})
|
||||
// double apply the same patch to the same package
|
||||
// this can occur in a monorepo when several packages
|
||||
// all try to apply the same patch
|
||||
const patchedAgainPkg = patcher(await patchedPkg) as ProjectManifest
|
||||
expect(patchedAgainPkg.peerDependencies).toStrictEqual({
|
||||
// the patch is applied only once (not 0 || 1 || 1)
|
||||
foo: '0 || 1',
|
||||
same: '12',
|
||||
multi: '16 || 17',
|
||||
mix: '1 || 4 || 2 || 3',
|
||||
partialmatch: '16 || 1.2.1 || 1',
|
||||
nopadding: '15.0.1 || 16 || ^17.0.1 || 18.x',
|
||||
})
|
||||
})
|
||||
|
||||
test('createPeerDependencyPatcher() overrides peerDependencies when parent>child selector is used', () => {
|
||||
const patcher = createPeerDependencyPatcher({
|
||||
allowedVersions: {
|
||||
bar: '2',
|
||||
'foo>bar': '1',
|
||||
'foo@2>bar': '2 || 3',
|
||||
'foo@>=2.3.5 <3>bar': '4',
|
||||
},
|
||||
})
|
||||
let patchedPkg = patcher({
|
||||
name: 'foo',
|
||||
peerDependencies: {
|
||||
bar: '0 || 1',
|
||||
},
|
||||
}) as ProjectManifest
|
||||
expect(patchedPkg.peerDependencies).toStrictEqual({
|
||||
bar: '0 || 1',
|
||||
})
|
||||
|
||||
patchedPkg = patcher({
|
||||
name: 'foo',
|
||||
version: '2',
|
||||
peerDependencies: {
|
||||
bar: '0 || 1',
|
||||
},
|
||||
}) as ProjectManifest
|
||||
expect(patchedPkg.peerDependencies).toStrictEqual({
|
||||
bar: '0 || 1 || 2 || 3',
|
||||
})
|
||||
|
||||
patchedPkg = patcher({
|
||||
name: 'foo',
|
||||
version: '3',
|
||||
peerDependencies: {
|
||||
bar: '0 || 1',
|
||||
},
|
||||
}) as ProjectManifest
|
||||
expect(patchedPkg.peerDependencies).toStrictEqual({
|
||||
bar: '0 || 1',
|
||||
})
|
||||
|
||||
patchedPkg = patcher({
|
||||
name: 'foo',
|
||||
version: '2.3.5',
|
||||
peerDependencies: {
|
||||
bar: '0 || 1',
|
||||
},
|
||||
}) as ProjectManifest
|
||||
expect(patchedPkg.peerDependencies).toStrictEqual({
|
||||
bar: '0 || 1 || 4',
|
||||
})
|
||||
})
|
||||
|
||||
// corner case exists when a 'parent>child' allowedVersion selector is used without a 'child' selector
|
||||
test('createPeerDependencyPatcher() corner case correctly applies override', () => {
|
||||
const patcher = createPeerDependencyPatcher({
|
||||
allowedVersions: {
|
||||
'foo>bar': '2',
|
||||
},
|
||||
})
|
||||
|
||||
const patchedPkg = patcher({
|
||||
name: 'foo',
|
||||
peerDependencies: {
|
||||
bar: '0 || 1',
|
||||
},
|
||||
}) as ProjectManifest
|
||||
expect(patchedPkg.peerDependencies).toStrictEqual({
|
||||
bar: '0 || 1 || 2',
|
||||
})
|
||||
})
|
||||
|
||||
test('createPeerDependencyPatcher() throws expected error if parent>child selector cannot parse', () => {
|
||||
expect(() => createPeerDependencyPatcher({
|
||||
allowedVersions: {
|
||||
'foo > bar': '2',
|
||||
},
|
||||
})).toThrowError('Cannot parse the "foo > bar" selector in pnpm.peerDependencyRules.allowedVersions')
|
||||
})
|
||||
@@ -15,37 +15,6 @@ test('createReadPackageHook() is passing directory to all hooks', async () => {
|
||||
expect(hook2).toBeCalledWith(manifest, dir)
|
||||
})
|
||||
|
||||
test('createReadPackageHook() runs the custom hook before the peer rules hook', async () => {
|
||||
const hook = jest.fn((manifest) => ({
|
||||
...manifest,
|
||||
dependencies: { ...manifest.peerDependencies },
|
||||
}))
|
||||
const readPackageHook = createReadPackageHook({
|
||||
ignoreCompatibilityDb: true,
|
||||
lockfileDir: '/foo',
|
||||
readPackageHook: [hook],
|
||||
peerDependencyRules: {
|
||||
allowAny: ['*'],
|
||||
},
|
||||
})
|
||||
const manifest = {
|
||||
peerDependencies: {
|
||||
react: '16',
|
||||
},
|
||||
}
|
||||
const dir = '/bar'
|
||||
const updatedManifest = await readPackageHook!(manifest, dir)
|
||||
expect(hook).toBeCalledWith(manifest, dir)
|
||||
expect(updatedManifest).toStrictEqual({
|
||||
dependencies: {
|
||||
react: '16',
|
||||
},
|
||||
peerDependencies: {
|
||||
react: '*',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('createReadPackageHook() runs the custom hook before the version overrider', async () => {
|
||||
const hook = jest.fn((manifest) => ({
|
||||
...manifest,
|
||||
|
||||
@@ -29,14 +29,19 @@
|
||||
"homepage": "https://github.com/pnpm/pnpm/blob/main/packages/render-peer-issues#readme",
|
||||
"funding": "https://opencollective.com/pnpm",
|
||||
"dependencies": {
|
||||
"@pnpm/error": "workspace:*",
|
||||
"@pnpm/matcher": "workspace:*",
|
||||
"@pnpm/parse-overrides": "workspace:*",
|
||||
"@pnpm/types": "workspace:*",
|
||||
"archy": "^1.0.0",
|
||||
"chalk": "^4.1.2",
|
||||
"cli-columns": "^4.0.0"
|
||||
"cli-columns": "^4.0.0",
|
||||
"semver": "^7.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@pnpm/render-peer-issues": "workspace:*",
|
||||
"@types/archy": "0.0.33",
|
||||
"@types/semver": "7.5.8",
|
||||
"strip-ansi": "^6.0.1"
|
||||
},
|
||||
"exports": {
|
||||
|
||||
@@ -1,19 +1,36 @@
|
||||
import { type BadPeerDependencyIssue, type PeerDependencyIssuesByProjects } from '@pnpm/types'
|
||||
import { PnpmError } from '@pnpm/error'
|
||||
import { createMatcher } from '@pnpm/matcher'
|
||||
import {
|
||||
type BadPeerDependencyIssue,
|
||||
type PeerDependencyIssuesByProjects,
|
||||
type PeerDependencyRules,
|
||||
} from '@pnpm/types'
|
||||
import { parseOverrides, type VersionOverride } from '@pnpm/parse-overrides'
|
||||
import archy from 'archy'
|
||||
import chalk from 'chalk'
|
||||
import cliColumns from 'cli-columns'
|
||||
import semver from 'semver'
|
||||
|
||||
export function renderPeerIssues (
|
||||
peerDependencyIssuesByProjects: PeerDependencyIssuesByProjects,
|
||||
opts?: { width?: number }
|
||||
opts?: {
|
||||
rules?: PeerDependencyRules
|
||||
width?: number
|
||||
}
|
||||
) {
|
||||
const ignoreMissingPatterns = [...new Set(opts?.rules?.ignoreMissing ?? [])]
|
||||
const ignoreMissingMatcher = createMatcher(ignoreMissingPatterns)
|
||||
const allowAnyPatterns = [...new Set(opts?.rules?.allowAny ?? [])]
|
||||
const allowAnyMatcher = createMatcher(allowAnyPatterns)
|
||||
const { allowedVersionsMatchAll, allowedVersionsByParentPkgName } = parseAllowedVersions(opts?.rules?.allowedVersions ?? {})
|
||||
const projects = {} as Record<string, PkgNode>
|
||||
for (const [projectId, { bad, missing, conflicts, intersections }] of Object.entries(peerDependencyIssuesByProjects)) {
|
||||
projects[projectId] = { dependencies: {}, peerIssues: [] }
|
||||
for (const [peerName, issues] of Object.entries(missing)) {
|
||||
if (
|
||||
!conflicts.includes(peerName) &&
|
||||
intersections[peerName] == null
|
||||
intersections[peerName] == null ||
|
||||
ignoreMissingMatcher(peerName)
|
||||
) {
|
||||
continue
|
||||
}
|
||||
@@ -22,7 +39,21 @@ export function renderPeerIssues (
|
||||
}
|
||||
}
|
||||
for (const [peerName, issues] of Object.entries(bad)) {
|
||||
if (allowAnyMatcher(peerName)) continue
|
||||
for (const issue of issues) {
|
||||
if (allowedVersionsMatchAll[peerName]?.some((range) => semver.satisfies(issue.foundVersion, range))) continue
|
||||
const currentParentPkg = issue.parents.at(-1)
|
||||
if (currentParentPkg && allowedVersionsByParentPkgName[peerName]?.[currentParentPkg.name]) {
|
||||
const allowedVersionsByParent = allowedVersionsByParentPkgName[peerName][currentParentPkg.name]
|
||||
.reduce((acc, { targetPkg, parentPkg, ranges }) => {
|
||||
if (!parentPkg.pref || currentParentPkg.version &&
|
||||
(isSubRange(parentPkg.pref, currentParentPkg.version) || semver.satisfies(currentParentPkg.version, parentPkg.pref))) {
|
||||
acc[targetPkg.name] = ranges
|
||||
}
|
||||
return acc
|
||||
}, {} as Record<string, string[]>)
|
||||
if (allowedVersionsByParent[peerName]?.some((range) => semver.satisfies(issue.foundVersion, range))) continue
|
||||
}
|
||||
createTree(projects[projectId], issue.parents, formatUnmetPeerMessage({
|
||||
peerName,
|
||||
...issue,
|
||||
@@ -109,3 +140,54 @@ function toArchyData (depName: string, pkgNode: PkgNode): archy.Data {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
type AllowedVersionsByParentPkgName = Record<string, Record<string, Array<Required<Pick<VersionOverride, 'parentPkg' | 'targetPkg'>> & { ranges: string[] }>>>
|
||||
|
||||
function parseAllowedVersions (allowedVersions: Record<string, string>) {
|
||||
const overrides = tryParseAllowedVersions(allowedVersions)
|
||||
const allowedVersionsMatchAll: Record<string, string[]> = {}
|
||||
const allowedVersionsByParentPkgName: AllowedVersionsByParentPkgName = {}
|
||||
for (const { parentPkg, targetPkg, newPref } of overrides) {
|
||||
const ranges = parseVersions(newPref)
|
||||
if (!parentPkg) {
|
||||
allowedVersionsMatchAll[targetPkg.name] = ranges
|
||||
continue
|
||||
}
|
||||
if (!allowedVersionsByParentPkgName[targetPkg.name]) {
|
||||
allowedVersionsByParentPkgName[targetPkg.name] = {}
|
||||
}
|
||||
if (!allowedVersionsByParentPkgName[targetPkg.name][parentPkg.name]) {
|
||||
allowedVersionsByParentPkgName[targetPkg.name][parentPkg.name] = []
|
||||
}
|
||||
allowedVersionsByParentPkgName[targetPkg.name][parentPkg.name].push({
|
||||
parentPkg,
|
||||
targetPkg,
|
||||
ranges,
|
||||
})
|
||||
}
|
||||
return {
|
||||
allowedVersionsMatchAll,
|
||||
allowedVersionsByParentPkgName,
|
||||
}
|
||||
}
|
||||
|
||||
function tryParseAllowedVersions (allowedVersions: Record<string, string>): VersionOverride[] {
|
||||
try {
|
||||
return parseOverrides(allowedVersions ?? {})
|
||||
} catch (err) {
|
||||
throw new PnpmError('INVALID_ALLOWED_VERSION_SELECTOR',
|
||||
`${(err as PnpmError).message} in pnpm.peerDependencyRules.allowedVersions`)
|
||||
}
|
||||
}
|
||||
|
||||
function parseVersions (versions: string): string[] {
|
||||
return versions.split('||').map(v => v.trim())
|
||||
}
|
||||
|
||||
function isSubRange (superRange: string | undefined, subRange: string) {
|
||||
return !superRange ||
|
||||
subRange === superRange ||
|
||||
semver.validRange(subRange) != null &&
|
||||
semver.validRange(superRange) != null &&
|
||||
semver.subset(subRange, superRange)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,13 @@ Peer dependencies that should be installed:
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`renderPeerIssues() allowed versions 1`] = `
|
||||
".
|
||||
└─┬ aaa 1.0.0
|
||||
└── ✕ unmet peer @foo/bar@^1.0.0: found 2.0.0
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`renderPeerIssues() format correctly the version ranges with spaces and "*" 1`] = `
|
||||
".
|
||||
└─┬ z 1.0.0
|
||||
|
||||
@@ -108,6 +108,185 @@ test('renderPeerIssues()', () => {
|
||||
}, { width: 500 }))).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('renderPeerIssues() ignore missing', () => {
|
||||
expect(stripAnsi(renderPeerIssues({
|
||||
'.': {
|
||||
missing: {
|
||||
aaa: [
|
||||
{
|
||||
parents: [
|
||||
{
|
||||
name: 'xxx',
|
||||
version: '1.0.0',
|
||||
},
|
||||
],
|
||||
optional: false,
|
||||
wantedRange: '>=1.0.0 <3.0.0',
|
||||
},
|
||||
],
|
||||
'@foo/bar': [
|
||||
{
|
||||
parents: [
|
||||
{
|
||||
name: 'xxx',
|
||||
version: '1.0.0',
|
||||
},
|
||||
],
|
||||
optional: false,
|
||||
wantedRange: '>=1.0.0 <3.0.0',
|
||||
},
|
||||
],
|
||||
},
|
||||
bad: {},
|
||||
conflicts: [],
|
||||
intersections: {
|
||||
aaa: '^1.0.0',
|
||||
'@foo/bar': '^1.0.0',
|
||||
},
|
||||
},
|
||||
}, {
|
||||
rules: {
|
||||
ignoreMissing: ['aaa', '@foo/*'],
|
||||
},
|
||||
width: 500,
|
||||
}))).toBe('')
|
||||
})
|
||||
|
||||
test('renderPeerIssues() allow any version', () => {
|
||||
expect(stripAnsi(renderPeerIssues({
|
||||
'.': {
|
||||
missing: {},
|
||||
bad: {
|
||||
bbb: [
|
||||
{
|
||||
parents: [
|
||||
{
|
||||
name: 'xxx',
|
||||
version: '1.0.0',
|
||||
},
|
||||
],
|
||||
foundVersion: '2.0.0',
|
||||
resolvedFrom: [],
|
||||
optional: false,
|
||||
wantedRange: '^1.0.0',
|
||||
},
|
||||
],
|
||||
'@foo/bar': [
|
||||
{
|
||||
parents: [
|
||||
{
|
||||
name: 'xxx',
|
||||
version: '1.0.0',
|
||||
},
|
||||
],
|
||||
foundVersion: '2.0.0',
|
||||
resolvedFrom: [],
|
||||
optional: false,
|
||||
wantedRange: '^1.0.0',
|
||||
},
|
||||
],
|
||||
},
|
||||
conflicts: [],
|
||||
intersections: {},
|
||||
},
|
||||
}, {
|
||||
rules: {
|
||||
allowAny: ['bbb', '@foo/*'],
|
||||
},
|
||||
width: 500,
|
||||
}))).toBe('')
|
||||
})
|
||||
|
||||
test('renderPeerIssues() allowed versions', () => {
|
||||
expect(stripAnsi(renderPeerIssues({
|
||||
'.': {
|
||||
missing: {},
|
||||
bad: {
|
||||
bbb: [
|
||||
{
|
||||
parents: [
|
||||
{
|
||||
name: 'xxx',
|
||||
version: '1.0.0',
|
||||
},
|
||||
],
|
||||
foundVersion: '2.0.0',
|
||||
resolvedFrom: [],
|
||||
optional: false,
|
||||
wantedRange: '^1.0.0',
|
||||
},
|
||||
],
|
||||
'@foo/bar': [
|
||||
{
|
||||
parents: [
|
||||
{
|
||||
name: 'aaa',
|
||||
version: '1.0.0',
|
||||
},
|
||||
],
|
||||
foundVersion: '2.0.0',
|
||||
resolvedFrom: [],
|
||||
optional: false,
|
||||
wantedRange: '^1.0.0',
|
||||
},
|
||||
{
|
||||
parents: [
|
||||
{
|
||||
name: 'yyy',
|
||||
version: '1.0.0',
|
||||
},
|
||||
{
|
||||
name: 'xxx',
|
||||
version: '1.0.0',
|
||||
},
|
||||
],
|
||||
foundVersion: '2.0.0',
|
||||
resolvedFrom: [],
|
||||
optional: false,
|
||||
wantedRange: '^1.0.0',
|
||||
},
|
||||
{
|
||||
parents: [
|
||||
{
|
||||
name: 'ccc',
|
||||
version: '3.0.0',
|
||||
},
|
||||
],
|
||||
foundVersion: '3.0.0',
|
||||
resolvedFrom: [],
|
||||
optional: false,
|
||||
wantedRange: '^1.0.0',
|
||||
},
|
||||
{
|
||||
parents: [
|
||||
{
|
||||
name: 'ccc',
|
||||
version: '2.3.6',
|
||||
},
|
||||
],
|
||||
foundVersion: '4.0.0',
|
||||
resolvedFrom: [],
|
||||
optional: false,
|
||||
wantedRange: '^1.0.0',
|
||||
},
|
||||
],
|
||||
},
|
||||
conflicts: [],
|
||||
intersections: {},
|
||||
},
|
||||
}, {
|
||||
rules: {
|
||||
allowedVersions: {
|
||||
bbb: '2',
|
||||
'xxx>@foo/bar': '2',
|
||||
'ccc@3>@foo/bar': '3',
|
||||
'ccc@>=2.3.5 <3>@foo/bar': '4',
|
||||
},
|
||||
},
|
||||
width: 500,
|
||||
}))).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('renderPeerIssues() optional peer dependencies are printed only if they are in conflict with non-optional peers', () => {
|
||||
expect(stripAnsi(renderPeerIssues({
|
||||
'.': {
|
||||
|
||||
@@ -9,6 +9,15 @@
|
||||
"../../__typings__/**/*.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../config/matcher"
|
||||
},
|
||||
{
|
||||
"path": "../../config/parse-overrides"
|
||||
},
|
||||
{
|
||||
"path": "../error"
|
||||
},
|
||||
{
|
||||
"path": "../types"
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
type SupportedArchitectures,
|
||||
type AllowedDeprecatedVersions,
|
||||
type PackageExtension,
|
||||
type PeerDependencyRules,
|
||||
type ReadPackageHook,
|
||||
type Registries,
|
||||
} from '@pnpm/types'
|
||||
@@ -105,7 +104,6 @@ export interface StrictInstallOptions {
|
||||
symlink: boolean
|
||||
enableModulesDir: boolean
|
||||
modulesCacheMaxAge: number
|
||||
peerDependencyRules: PeerDependencyRules
|
||||
allowedDeprecatedVersions: AllowedDeprecatedVersions
|
||||
allowNonAppliedPatches: boolean
|
||||
preferSymlinkedExecutables: boolean
|
||||
@@ -265,24 +263,12 @@ export function extendOptions (
|
||||
...opts,
|
||||
storeDir: defaultOpts.storeDir,
|
||||
}
|
||||
if (extendedOpts.autoInstallPeers) {
|
||||
if (extendedOpts.peerDependencyRules?.ignoreMissing?.length) {
|
||||
throw new PnpmError('IGNORE_MISSING_WITH_AUTO_INSTALL_PEERS', 'Cannot have both autoInstallPeers=true and setting peerDependencyRules.ignoreMissing')
|
||||
}
|
||||
if (extendedOpts.peerDependencyRules?.allowAny?.length) {
|
||||
throw new PnpmError('ALLOW_ANY_WITH_AUTO_INSTALL_PEERS', 'Cannot have both autoInstallPeers=true and setting peerDependencyRules.allowAny')
|
||||
}
|
||||
if (Object.keys(extendedOpts.peerDependencyRules?.allowedVersions ?? {}).length) {
|
||||
throw new PnpmError('ALLOWED_VERSIONS_WITH_AUTO_INSTALL_PEERS', 'Cannot have both autoInstallPeers=true and setting peerDependencyRules.allowedVersions')
|
||||
}
|
||||
}
|
||||
extendedOpts.readPackageHook = createReadPackageHook({
|
||||
ignoreCompatibilityDb: extendedOpts.ignoreCompatibilityDb,
|
||||
readPackageHook: extendedOpts.hooks?.readPackage,
|
||||
overrides: extendedOpts.overrides,
|
||||
lockfileDir: extendedOpts.lockfileDir,
|
||||
packageExtensions: extendedOpts.packageExtensions,
|
||||
peerDependencyRules: extendedOpts.peerDependencyRules,
|
||||
ignoredOptionalDependencies: extendedOpts.ignoredOptionalDependencies,
|
||||
})
|
||||
if (extendedOpts.lockfileOnly) {
|
||||
|
||||
@@ -602,33 +602,3 @@ test('do not override the direct dependency with an auto installed peer dependen
|
||||
const lockfile = project.readLockfile()
|
||||
expect(lockfile.importers['.'].dependencies?.rxjs.version).toStrictEqual('6.6.7')
|
||||
})
|
||||
|
||||
test('auto install peers fails if ignoreMissing is set', async () => {
|
||||
prepareEmpty()
|
||||
await expect(addDependenciesToPackage({}, ['is-odd@1.0.0'], testDefaults({
|
||||
autoInstallPeers: true,
|
||||
peerDependencyRules: {
|
||||
ignoreMissing: ['*'],
|
||||
},
|
||||
}))).rejects.toThrow('Cannot have both autoInstallPeers=true and setting peerDependencyRules.ignoreMissing')
|
||||
})
|
||||
|
||||
test('auto install peers fails if allowAny is set', async () => {
|
||||
prepareEmpty()
|
||||
await expect(addDependenciesToPackage({}, ['is-odd@1.0.0'], testDefaults({
|
||||
autoInstallPeers: true,
|
||||
peerDependencyRules: {
|
||||
allowAny: ['*'],
|
||||
},
|
||||
}))).rejects.toThrow('Cannot have both autoInstallPeers=true and setting peerDependencyRules.allowAny')
|
||||
})
|
||||
|
||||
test('auto install peers fails if allowedVersions is set', async () => {
|
||||
prepareEmpty()
|
||||
await expect(addDependenciesToPackage({}, ['is-odd@1.0.0'], testDefaults({
|
||||
autoInstallPeers: true,
|
||||
peerDependencyRules: {
|
||||
allowedVersions: { react: '*' },
|
||||
},
|
||||
}))).rejects.toThrow('Cannot have both autoInstallPeers=true and setting peerDependencyRules.allowedVersions')
|
||||
})
|
||||
|
||||
44
pnpm-lock.yaml
generated
44
pnpm-lock.yaml
generated
@@ -2776,6 +2776,15 @@ importers:
|
||||
|
||||
packages/render-peer-issues:
|
||||
dependencies:
|
||||
'@pnpm/error':
|
||||
specifier: workspace:*
|
||||
version: link:../error
|
||||
'@pnpm/matcher':
|
||||
specifier: workspace:*
|
||||
version: link:../../config/matcher
|
||||
'@pnpm/parse-overrides':
|
||||
specifier: workspace:*
|
||||
version: link:../../config/parse-overrides
|
||||
'@pnpm/types':
|
||||
specifier: workspace:*
|
||||
version: link:../types
|
||||
@@ -2788,6 +2797,9 @@ importers:
|
||||
cli-columns:
|
||||
specifier: ^4.0.0
|
||||
version: 4.0.0
|
||||
semver:
|
||||
specifier: ^7.6.0
|
||||
version: 7.6.0
|
||||
devDependencies:
|
||||
'@pnpm/render-peer-issues':
|
||||
specifier: workspace:*
|
||||
@@ -2795,6 +2807,9 @@ importers:
|
||||
'@types/archy':
|
||||
specifier: 0.0.33
|
||||
version: 0.0.33
|
||||
'@types/semver':
|
||||
specifier: 7.5.8
|
||||
version: 7.5.8
|
||||
strip-ansi:
|
||||
specifier: ^6.0.1
|
||||
version: 6.0.1
|
||||
@@ -7187,7 +7202,7 @@ packages:
|
||||
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
|
||||
|
||||
/@eslint-community/regexpp@4.10.0:
|
||||
resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==}
|
||||
@@ -7930,7 +7945,7 @@ packages:
|
||||
engines: {node: ^16.0.0 || >=18.0.0}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha
|
||||
eslint: '*'
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
@@ -7940,7 +7955,7 @@ packages:
|
||||
resolution: {integrity: sha512-zct/MdJnVaRRNy9e84XnVtRv9Vf91/qqe+hZJtKanjojud4wAVy/7lXxJmMyX6X6J+xc6c//YEWvpeif8cAhWA==}
|
||||
engines: {node: ^16.0.0 || >=18.0.0}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
@@ -7954,7 +7969,7 @@ packages:
|
||||
resolution: {integrity: sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q==}
|
||||
engines: {node: ^16.0.0 || >=18.0.0}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
@@ -7977,7 +7992,7 @@ packages:
|
||||
resolution: {integrity: sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==}
|
||||
engines: {node: ^16.0.0 || >=18.0.0}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
|
||||
/@typescript-eslint/visitor-keys@6.18.1:
|
||||
resolution: {integrity: sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==}
|
||||
@@ -9199,13 +9214,13 @@ packages:
|
||||
resolution: {integrity: sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==}
|
||||
engines: {node: '>=12'}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
eslint: '>=6.0.0'
|
||||
|
||||
/eslint-config-standard-with-typescript@39.1.1:
|
||||
resolution: {integrity: sha512-t6B5Ep8E4I18uuoYeYxINyqcXb2UbC0SOOTxRtBSt2JUs+EzeXbfe2oaiPs71AIdnoWhXDO2fYOHz8df3kV84A==}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/eslint-plugin': ^6.4.0
|
||||
eslint: '*'
|
||||
eslint: ^8.0.1
|
||||
eslint-plugin-import: ^2.25.2
|
||||
eslint-plugin-n: '^15.0.0 || ^16.0.0 '
|
||||
eslint-plugin-promise: ^6.0.0
|
||||
@@ -9215,7 +9230,7 @@ packages:
|
||||
resolution: {integrity: sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
eslint: ^8.0.1
|
||||
eslint-plugin-import: ^2.25.2
|
||||
eslint-plugin-n: '^15.0.0 || ^16.0.0 '
|
||||
eslint-plugin-promise: ^6.0.0
|
||||
@@ -9248,20 +9263,20 @@ packages:
|
||||
resolution: {integrity: sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
eslint: '>=8'
|
||||
|
||||
/eslint-plugin-es@3.0.1:
|
||||
resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
eslint: '>=4.19.1'
|
||||
|
||||
/eslint-plugin-import@2.29.1:
|
||||
resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': '*'
|
||||
eslint: '*'
|
||||
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
|
||||
peerDependenciesMeta:
|
||||
'@typescript-eslint/parser':
|
||||
optional: true
|
||||
@@ -9270,19 +9285,19 @@ packages:
|
||||
resolution: {integrity: sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
eslint: '>=7.0.0'
|
||||
|
||||
/eslint-plugin-node@11.1.0:
|
||||
resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
eslint: '>=5.16.0'
|
||||
|
||||
/eslint-plugin-promise@6.1.1:
|
||||
resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
|
||||
/eslint-scope@7.2.2:
|
||||
resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
|
||||
@@ -21448,6 +21463,7 @@ time:
|
||||
/@types/rimraf@3.0.2: '2021-08-18T21:02:03.570Z'
|
||||
/@types/semver@7.5.3: '2023-09-25T14:19:37.089Z'
|
||||
/@types/semver@7.5.7: '2024-02-11T14:35:16.597Z'
|
||||
/@types/semver@7.5.8: '2024-02-24T16:35:29.020Z'
|
||||
/@types/signal-exit@3.0.4: '2023-11-07T16:33:34.502Z'
|
||||
/@types/sinon@10.0.20: '2023-10-18T15:02:12.573Z'
|
||||
/@types/ssri@7.1.5: '2023-11-21T01:08:19.305Z'
|
||||
|
||||
@@ -27,6 +27,7 @@ export function initReporter (
|
||||
throttleProgress: 200,
|
||||
hideAddedPkgsProgress: opts.config.lockfileOnly,
|
||||
hideLifecyclePrefix: opts.config.reporterHidePrefix,
|
||||
peerDependencyRules: opts.config.rootProjectManifest?.pnpm?.peerDependencyRules,
|
||||
},
|
||||
streamParser,
|
||||
})
|
||||
@@ -44,6 +45,7 @@ export function initReporter (
|
||||
logLevel: opts.config.loglevel as LogLevel,
|
||||
throttleProgress: 1000,
|
||||
hideLifecyclePrefix: opts.config.reporterHidePrefix,
|
||||
peerDependencyRules: opts.config.rootProjectManifest?.pnpm?.peerDependencyRules,
|
||||
},
|
||||
streamParser,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user