mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-10 18:18:56 -04:00
33
.changeset/forty-lies-work.md
Normal file
33
.changeset/forty-lies-work.md
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
"@pnpm/resolve-dependencies": patch
|
||||
"supi": patch
|
||||
---
|
||||
|
||||
The lockfile should be correctly updated when a direct dependency that has peer dependencies has a new version specifier in `package.json`.
|
||||
|
||||
For instance, `jest@26` has `cascade@2` in its peer dependencies. So `pnpm install` will scope Jest to some version of cascade. This is how it will look like in `pnpm-lock.yaml`:
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
canvas: 2.6.0
|
||||
jest: 26.4.0_canvas@2.6.0
|
||||
```
|
||||
|
||||
If the version specifier of Jest gets changed in the `package.json` to `26.5.0`, the next time `pnpm install` is executed, the lockfile should be changed to this:
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
canvas: 2.6.0
|
||||
jest: 26.5.0_canvas@2.6.0
|
||||
```
|
||||
|
||||
Prior to this fix, after the update, Jest was not scoped with canvas, so the lockfile was incorrectly updated to the following:
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
canvas: 2.6.0
|
||||
jest: 26.5.0
|
||||
```
|
||||
|
||||
Related issue: [#2919](https://github.com/pnpm/pnpm/issues/2919).
|
||||
Related PR: [#2920](https://github.com/pnpm/pnpm/pull/2920).
|
||||
@@ -3,6 +3,7 @@ import './add'
|
||||
import './addRecursive'
|
||||
import './linkRecursive'
|
||||
import './miscRecursive'
|
||||
import './peerDependencies'
|
||||
import './prune'
|
||||
import './remove/completion'
|
||||
import './remove/remove'
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import { add, install } from '@pnpm/plugin-commands-installation'
|
||||
import prepare from '@pnpm/prepare'
|
||||
import { REGISTRY_MOCK_PORT } from '@pnpm/registry-mock'
|
||||
import test = require('tape')
|
||||
import tempy = require('tempy')
|
||||
|
||||
const REGISTRY_URL = `http://localhost:${REGISTRY_MOCK_PORT}`
|
||||
|
||||
const DEFAULT_OPTIONS = {
|
||||
argv: {
|
||||
original: [],
|
||||
},
|
||||
bail: false,
|
||||
cliOptions: {},
|
||||
include: {
|
||||
dependencies: true,
|
||||
devDependencies: true,
|
||||
optionalDependencies: true,
|
||||
},
|
||||
lock: true,
|
||||
pnpmfile: 'pnpmfile.js',
|
||||
rawConfig: { registry: REGISTRY_URL },
|
||||
rawLocalConfig: { registry: REGISTRY_URL },
|
||||
registries: {
|
||||
default: REGISTRY_URL,
|
||||
},
|
||||
sort: true,
|
||||
storeDir: tempy.directory(),
|
||||
workspaceConcurrency: 1,
|
||||
}
|
||||
|
||||
test('root dependency that has a peer is correctly updated after its version changes', async (t) => {
|
||||
const project = prepare(t, {})
|
||||
|
||||
await add.handler({
|
||||
...DEFAULT_OPTIONS,
|
||||
dir: process.cwd(),
|
||||
linkWorkspacePackages: true,
|
||||
}, ['ajv@4.10.4', 'ajv-keywords@1.5.0'])
|
||||
|
||||
{
|
||||
const lockfile = await project.readLockfile()
|
||||
t.equal(lockfile.dependencies['ajv-keywords'], '1.5.0_ajv@4.10.4')
|
||||
}
|
||||
|
||||
await project.writePackageJson({
|
||||
dependencies: {
|
||||
ajv: '4.10.4',
|
||||
'ajv-keywords': '1.5.1',
|
||||
},
|
||||
})
|
||||
|
||||
await install.handler({
|
||||
...DEFAULT_OPTIONS,
|
||||
dir: process.cwd(),
|
||||
linkWorkspacePackages: true,
|
||||
rawLocalConfig: {
|
||||
'frozen-lockfile': false,
|
||||
},
|
||||
})
|
||||
|
||||
{
|
||||
const lockfile = await project.readLockfile()
|
||||
t.equal(lockfile.dependencies['ajv-keywords'], '1.5.1_ajv@4.10.4')
|
||||
}
|
||||
|
||||
t.end()
|
||||
})
|
||||
@@ -358,7 +358,7 @@ function getDepsToResolve (
|
||||
// The only reason we resolve children in case the package depends on peers
|
||||
// is to get information about the existing dependencies, so that they can
|
||||
// be merged with the resolved peers.
|
||||
const proceedAll = options.proceed
|
||||
let proceedAll = options.proceed
|
||||
const allPeers = new Set<string>()
|
||||
for (const wantedDependency of wantedDependencies) {
|
||||
let reference = wantedDependency.alias && resolvedDependencies[wantedDependency.alias]
|
||||
@@ -394,6 +394,15 @@ function getDepsToResolve (
|
||||
allPeers.add(peerName)
|
||||
})
|
||||
}
|
||||
if (!infoFromLockfile && !proceedAll) {
|
||||
// In this case we don't know if the package depends on peer dependencies, so we proceed all.
|
||||
proceedAll = true
|
||||
for (const extendedWantedDep of extendedWantedDeps) {
|
||||
if (!extendedWantedDep.proceed) {
|
||||
extendedWantedDep.proceed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
extendedWantedDeps.push({
|
||||
infoFromLockfile,
|
||||
proceed,
|
||||
|
||||
@@ -850,7 +850,7 @@ async function toResolveImporter (
|
||||
project: ImporterToUpdate
|
||||
) {
|
||||
const allDeps = getWantedDependencies(project.manifest)
|
||||
const { linkedAliases, nonLinkedDependencies } = await partitionLinkedPackages(allDeps, {
|
||||
const { nonLinkedDependencies } = await partitionLinkedPackages(allDeps, {
|
||||
lockfileOnly: opts.lockfileOnly,
|
||||
modulesDir: project.modulesDir,
|
||||
projectDir: project.rootDir,
|
||||
@@ -890,8 +890,7 @@ async function toResolveImporter (
|
||||
...project,
|
||||
hasRemovedDependencies: Boolean(project.removePackages?.length),
|
||||
preferredVersions: opts.preferredVersions ?? (project.manifest && getPreferredVersionsFromPackage(project.manifest)) ?? {},
|
||||
wantedDependencies: wantedDependencies
|
||||
.filter(({ alias, updateDepth }) => updateDepth >= 0 || !linkedAliases.has(alias)),
|
||||
wantedDependencies,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user