mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-10 18:18:56 -04:00
18
.changeset/long-brooms-look.md
Normal file
18
.changeset/long-brooms-look.md
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -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 (
|
||||
|
||||
38
packages/supi/test/createVersionOverrider.test.ts
Normal file
38
packages/supi/test/createVersionOverrider.test.ts
Normal 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()
|
||||
})
|
||||
@@ -3,6 +3,7 @@ import './allProjectsAreUpToDate.test'
|
||||
import './api'
|
||||
import './breakingChanges'
|
||||
import './cache'
|
||||
import './createVersionOverrider.test'
|
||||
import './install'
|
||||
import './link'
|
||||
import './lockfile'
|
||||
|
||||
@@ -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',
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user