Skip to content

Commit

Permalink
feat: support $ in overrides instead of specific version #5703 (#5704)
Browse files Browse the repository at this point in the history
Co-authored-by: Zoltan Kochan <z@kochan.io>
  • Loading branch information
thinkhalo and zkochan committed Nov 29, 2022
1 parent b14a7fd commit 4097af6
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 1 deletion.
20 changes: 20 additions & 0 deletions .changeset/flat-lobsters-whisper.md
@@ -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
Expand All @@ -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
Expand All @@ -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}".`
)
}
Expand Up @@ -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".')
})

0 comments on commit 4097af6

Please sign in to comment.