mirror of
https://github.com/pnpm/pnpm.git
synced 2026-02-15 09:33:45 -05:00
Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
20
.changeset/flat-lobsters-whisper.md
Normal file
20
.changeset/flat-lobsters-whisper.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
"@pnpm/plugin-commands-installation": minor
|
||||
"pnpm": minor
|
||||
---
|
||||
|
||||
Overrides may be defined as a reference to a spec for a direct dependency by prefixing the name of the package you wish the version to match with a `$`.
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"foo": "^1.0.0"
|
||||
},
|
||||
"overrides": {
|
||||
// the override is defined as a reference to the dependency
|
||||
"foo": "$foo",
|
||||
// the referenced package does not need to match the overridden one
|
||||
"bar": "$foo"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1,9 +1,11 @@
|
||||
import { PnpmError } from '@pnpm/error'
|
||||
import {
|
||||
AllowedDeprecatedVersions,
|
||||
PackageExtension,
|
||||
PeerDependencyRules,
|
||||
ProjectManifest,
|
||||
} from '@pnpm/types'
|
||||
import mapValues from 'ramda/src/map'
|
||||
|
||||
export function getOptionsFromRootManifest (manifest: ProjectManifest): {
|
||||
allowedDeprecatedVersions?: AllowedDeprecatedVersions
|
||||
@@ -18,7 +20,10 @@ export function getOptionsFromRootManifest (manifest: ProjectManifest): {
|
||||
// We read Yarn's resolutions field for compatibility
|
||||
// but we really replace the version specs to any other version spec, not only to exact versions,
|
||||
// so we cannot call it resolutions
|
||||
const overrides = manifest.pnpm?.overrides ?? manifest.resolutions
|
||||
const overrides = mapValues(
|
||||
createVersionReferencesReplacer(manifest),
|
||||
manifest.pnpm?.overrides ?? manifest.resolutions ?? {}
|
||||
)
|
||||
const neverBuiltDependencies = manifest.pnpm?.neverBuiltDependencies
|
||||
const onlyBuiltDependencies = manifest.pnpm?.onlyBuiltDependencies
|
||||
const packageExtensions = manifest.pnpm?.packageExtensions
|
||||
@@ -40,3 +45,23 @@ export function getOptionsFromRootManifest (manifest: ProjectManifest): {
|
||||
}
|
||||
return settings
|
||||
}
|
||||
|
||||
function createVersionReferencesReplacer (manifest: ProjectManifest) {
|
||||
const allDeps = {
|
||||
...manifest.devDependencies,
|
||||
...manifest.dependencies,
|
||||
...manifest.optionalDependencies,
|
||||
}
|
||||
return replaceVersionReferences.bind(null, allDeps)
|
||||
}
|
||||
|
||||
function replaceVersionReferences (dep: Record<string, string>, spec: string) {
|
||||
if (!spec.startsWith('$')) return spec
|
||||
const dependencyName = spec.slice(1)
|
||||
const newSpec = dep[dependencyName]
|
||||
if (newSpec) return newSpec
|
||||
throw new PnpmError(
|
||||
'CANNOT_RESOLVE_OVERRIDE_VERSION',
|
||||
`Cannot resolve version ${spec} in overrides. The direct dependencies don't have dependency "${dependencyName}".`
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,3 +19,61 @@ test('getOptionsFromRootManifest() should read "overrides" field', () => {
|
||||
})
|
||||
expect(options.overrides).toStrictEqual({ foo: '1.0.0' })
|
||||
})
|
||||
|
||||
test('getOptionsFromRootManifest() Support $ in overrides by dependencies', () => {
|
||||
const options = getOptionsFromRootManifest({
|
||||
dependencies: {
|
||||
foo: '1.0.0',
|
||||
},
|
||||
pnpm: {
|
||||
overrides: {
|
||||
foo: '$foo',
|
||||
},
|
||||
},
|
||||
})
|
||||
expect(options.overrides).toStrictEqual({ foo: '1.0.0' })
|
||||
})
|
||||
|
||||
test('getOptionsFromRootManifest() Support $ in overrides by devDependencies', () => {
|
||||
const options = getOptionsFromRootManifest({
|
||||
devDependencies: {
|
||||
foo: '1.0.0',
|
||||
},
|
||||
pnpm: {
|
||||
overrides: {
|
||||
foo: '$foo',
|
||||
},
|
||||
},
|
||||
})
|
||||
expect(options.overrides).toStrictEqual({ foo: '1.0.0' })
|
||||
})
|
||||
|
||||
test('getOptionsFromRootManifest() Support $ in overrides by dependencies and devDependencies', () => {
|
||||
const options = getOptionsFromRootManifest({
|
||||
dependencies: {
|
||||
foo: '1.0.0',
|
||||
},
|
||||
devDependencies: {
|
||||
foo: '2.0.0',
|
||||
},
|
||||
pnpm: {
|
||||
overrides: {
|
||||
foo: '$foo',
|
||||
},
|
||||
},
|
||||
})
|
||||
expect(options.overrides).toStrictEqual({ foo: '1.0.0' })
|
||||
})
|
||||
|
||||
test('getOptionsFromRootManifest() throws an error if cannot resolve an override version reference', () => {
|
||||
expect(() => getOptionsFromRootManifest({
|
||||
dependencies: {
|
||||
bar: '1.0.0',
|
||||
},
|
||||
pnpm: {
|
||||
overrides: {
|
||||
foo: '$foo',
|
||||
},
|
||||
},
|
||||
})).toThrow('Cannot resolve version $foo in overrides. The direct dependencies don\'t have dependency "foo".')
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user