Files
pnpm/patching/config/src/getPatchInfo.ts
Khải 5f7be645e4 feat(patching): version ranges and strict patches (#9236)
* feat: replace a config

This is a test commit to see if CI fails

* feat: `strictPatches`

* docs: future instruction

* feat: `strictPatches` → `allowPatchFailure`

* docs(changeset): correction

* test: getOptionsFromRootManifest

* fix: allowFailure

* feat: groupPatchedDependencies

* fix: update code after merge

* fix: star spec

* feat: error on invalid ranges

* fix: eslint

* docs: change task

* feat(patching): version ranges

* fix: `verifyPatches`

* refactor: move types to `@pnpm/patching.types`

* docs(changeset): add missing package

* refactor: move `verifyPatches` to `@pnpm/patching.config`

* test: fix

* feat: change error message of unused patches

* refactor: exact options into an interface

* test(patching): version range

* test(patching): allowPatchFailure

* docs: change wording

* docs: change wording

* test(patching): version range error

* test(patching): legacy behavior

* test: don't use star

* test(patching): strict versionless

* test: strictPatches

* chore(deps): `@pnpm/logger` must be peer

* docs: fix grammar

* refactor: rename `blank` to `all`

* refactor: use string

* refactor: use array for `PatchGroup.range`

* refactor: stop re-exporting `allPatchKeys`

* feat: re-export `PatchGroupRangeItem`

* refactor: move error creation into a class

* docs: replace "versionless" with "name-only"

* docs: coherent wordings

* test: exact version overrides range conflict

* test: tweak

* docs: consistent wordings

* docs: correct wordings

* refactor: rename `allowPatchFailure` to `ignorePatchFailures`

* feat: replace `strictPatches` with `ignorePatchFailures`

* docs: legacy behavior

* feat: introduce `allowUnusedPatches`

* docs(changeset): update

* docs: remove outdated comment

* docs: backward-compatibility
2025-03-13 12:13:06 +01:00

40 lines
1.3 KiB
TypeScript

import { PnpmError } from '@pnpm/error'
import { type ExtendedPatchInfo, type PatchGroupRangeItem, type PatchGroupRecord } from '@pnpm/patching.types'
import { satisfies } from 'semver'
class PatchKeyConflictError extends PnpmError {
constructor (
pkgName: string,
pkgVersion: string,
satisfied: Array<Pick<PatchGroupRangeItem, 'version'>>
) {
const pkgId = `${pkgName}@${pkgVersion}`
const satisfiedVersions = satisfied.map(({ version }) => version)
const message = `Unable to choose between ${satisfied.length} version ranges to patch ${pkgId}: ${satisfiedVersions.join(', ')}`
super('PATCH_KEY_CONFLICT', message, {
hint: `Explicitly set the exact version (${pkgId}) to resolve conflict`,
})
}
}
export function getPatchInfo (
patchFileGroups: PatchGroupRecord | undefined,
pkgName: string,
pkgVersion: string
): ExtendedPatchInfo | undefined {
if (!patchFileGroups?.[pkgName]) return undefined
const exactVersion = patchFileGroups[pkgName].exact[pkgVersion]
if (exactVersion) return exactVersion
const satisfied = patchFileGroups[pkgName].range.filter(item => satisfies(pkgVersion, item.version))
if (satisfied.length > 1) {
throw new PatchKeyConflictError(pkgName, pkgVersion, satisfied)
}
if (satisfied.length === 1) {
return satisfied[0].patch
}
return patchFileGroups[pkgName].all
}