feat: specifying the parent of the overriden dependency

PR #2947
This commit is contained in:
Zoltan Kochan
2020-10-22 23:57:48 +03:00
committed by GitHub
parent b5d694e7ff
commit c03a2b2cbc
5 changed files with 106 additions and 8 deletions

View File

@@ -0,0 +1,18 @@
---
"supi": patch
---
Allow to specify the overriden dependency's parent package.
For example, if `foo` should be overriden only in dependencies of bar v2, this configuration may be used:
```json
{
...
"pnpm": {
"overriden": {
"bar@2>foo": "1.0.0"
}
}
}
```

View File

@@ -1,20 +1,42 @@
import { Dependencies, PackageManifest, ReadPackageHook } from '@pnpm/types'
import parseWantedDependency from '@pnpm/parse-wanted-dependency'
import semver = require('semver')
export default function (overrides: Record<string, string>): ReadPackageHook {
const versionOverrides = Object.entries(overrides)
.map(([rawWantedDependency, newPref]) => ({
newPref,
wantedDependency: parseWantedDependency(rawWantedDependency),
} as VersionOverride))
const genericVersionOverrides = [] as VersionOverride[]
const versionOverrides = [] as VersionOverrideWithParent[]
Object.entries(overrides)
.forEach(([selector, newPref]) => {
if (selector.includes('>')) {
const [parentSelector, childSelector] = selector.split('>')
versionOverrides.push({
newPref,
parentWantedDependency: parseWantedDependency(parentSelector),
wantedDependency: parseWantedDependency(childSelector),
} as VersionOverrideWithParent)
return
}
genericVersionOverrides.push({
newPref,
wantedDependency: parseWantedDependency(selector),
} as VersionOverride)
})
return ((pkg: PackageManifest) => {
if (pkg.dependencies) overrideDeps(versionOverrides, pkg.dependencies)
if (pkg.optionalDependencies) overrideDeps(versionOverrides, pkg.optionalDependencies)
overrideDepsOfPkg(pkg, versionOverrides.filter(({ parentWantedDependency }) => {
return parentWantedDependency.alias === pkg.name && (
!parentWantedDependency.pref || semver.satisfies(pkg.version, parentWantedDependency.pref)
)
}))
overrideDepsOfPkg(pkg, genericVersionOverrides)
return pkg
}) as ReadPackageHook
}
interface VersionOverride {
parentWantedDependency?: {
alias: string
pref?: string
}
wantedDependency: {
alias: string
pref?: string
@@ -22,6 +44,19 @@ interface VersionOverride {
newPref: string
}
interface VersionOverrideWithParent extends VersionOverride {
parentWantedDependency: {
alias: string
pref?: string
}
}
function overrideDepsOfPkg (pkg: PackageManifest, versionOverrides: VersionOverride[]) {
if (pkg.dependencies) overrideDeps(versionOverrides, pkg.dependencies)
if (pkg.optionalDependencies) overrideDeps(versionOverrides, pkg.optionalDependencies)
return pkg
}
function overrideDeps (versionOverrides: VersionOverride[], deps: Dependencies) {
for (const versionOverride of versionOverrides) {
if (

View File

@@ -0,0 +1,38 @@
import createVersionOverrider from 'supi/lib/install/createVersionsOverrider'
import promisifyTape from 'tape-promise'
import tape = require('tape')
const test = promisifyTape(tape)
test('createVersionsOverrider() overrides dependencies of specified packages only', (t: tape.Test) => {
const overrider = createVersionOverrider({
'foo@1>bar@^1.2.0': '3.0.0',
})
t.deepEqual(overrider({
name: 'foo',
version: '1.2.0',
dependencies: {
bar: '^1.2.0',
},
}), {
name: 'foo',
version: '1.2.0',
dependencies: {
bar: '3.0.0',
},
})
t.deepEqual(overrider({
name: 'foo',
version: '2.0.0',
dependencies: {
bar: '^1.2.0',
},
}), {
name: 'foo',
version: '2.0.0',
dependencies: {
bar: '^1.2.0',
},
})
t.end()
})

View File

@@ -3,6 +3,7 @@ import './allProjectsAreUpToDate.test'
import './api'
import './breakingChanges'
import './cache'
import './createVersionOverrider.test'
import './install'
import './link'
import './lockfile'

View File

@@ -13,21 +13,26 @@ test('versions are replaced with versions specified through pnpm.overrides field
const project = prepareEmpty(t)
await addDistTag({ package: 'bar', version: '100.0.0', distTag: 'latest' })
await addDistTag({ package: 'foo', version: '100.0.0', distTag: 'latest' })
const manifest = await addDependenciesToPackage({
pnpm: {
overrides: {
'foobarqar>foo': 'npm:qar@100.0.0',
'bar@^100.0.0': '100.1.0',
'dep-of-pkg-with-1-dep': '101.0.0',
},
},
}, ['pkg-with-1-dep@100.0.0', 'foobar@100.0.0'], await testDefaults())
}, ['pkg-with-1-dep@100.0.0', 'foobar@100.0.0', 'foobarqar@1.0.0'], await testDefaults())
{
const lockfile = await project.readLockfile()
t.equal(lockfile.packages['/foobarqar/1.0.0'].dependencies['foo'], '/qar/100.0.0')
t.equal(lockfile.packages['/foobar/100.0.0'].dependencies['foo'], '100.0.0')
t.ok(lockfile.packages['/dep-of-pkg-with-1-dep/101.0.0'])
t.ok(lockfile.packages['/bar/100.1.0'])
t.deepEqual(lockfile.overrides, {
'foobarqar>foo': 'npm:qar@100.0.0',
'bar@^100.0.0': '100.1.0',
'dep-of-pkg-with-1-dep': '101.0.0',
})
@@ -49,6 +54,7 @@ test('versions are replaced with versions specified through pnpm.overrides field
t.ok(lockfile.packages['/dep-of-pkg-with-1-dep/101.0.0'])
t.ok(lockfile.packages['/bar/100.0.0'])
t.deepEqual(lockfile.overrides, {
'foobarqar>foo': 'npm:qar@100.0.0',
'bar@^100.0.0': '100.0.0',
'dep-of-pkg-with-1-dep': '101.0.0',
})