@pnpm/engine.pm.commands 1101.1.2 → 1101.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/self-updater/selfUpdate.js +47 -0
- package/package.json +23 -22
|
@@ -6,6 +6,7 @@ import { parsePackageManager, types as allTypes } from '@pnpm/config.reader';
|
|
|
6
6
|
import { PnpmError } from '@pnpm/error';
|
|
7
7
|
import { createResolver } from '@pnpm/installing.client';
|
|
8
8
|
import { resolvePackageManagerIntegrities } from '@pnpm/installing.env-installer';
|
|
9
|
+
import { readEnvLockfile } from '@pnpm/lockfile.fs';
|
|
9
10
|
import { globalInfo, globalWarn } from '@pnpm/logger';
|
|
10
11
|
import { whichVersionIsPinned } from '@pnpm/resolving.npm-resolver';
|
|
11
12
|
import { createStoreController } from '@pnpm/store.connection-manager';
|
|
@@ -51,6 +52,12 @@ export async function handler(opts, params) {
|
|
|
51
52
|
globalInfo('Checking for updates...');
|
|
52
53
|
const { resolve } = createResolver({ ...opts, configByUri: opts.configByUri });
|
|
53
54
|
const pkgName = 'pnpm';
|
|
55
|
+
// `pnpm self-update` (no args) defaults to the `latest` dist-tag, but we
|
|
56
|
+
// refuse to downgrade in that case — `latest` on the registry can lag the
|
|
57
|
+
// installed version when a new major has shipped without being tagged.
|
|
58
|
+
// `pnpm self-update latest` (explicit) bypasses the guard so users can
|
|
59
|
+
// still force a downgrade when they want one.
|
|
60
|
+
const isImplicitLatest = params.length === 0;
|
|
54
61
|
const bareSpecifier = params[0] ?? 'latest';
|
|
55
62
|
const resolution = await resolve({ alias: pkgName, bareSpecifier }, {
|
|
56
63
|
lockfileDir: opts.lockfileDir ?? opts.dir,
|
|
@@ -87,6 +94,15 @@ export async function handler(opts, params) {
|
|
|
87
94
|
}
|
|
88
95
|
if (opts.wantedPackageManager?.name === packageManager.name) {
|
|
89
96
|
if (opts.wantedPackageManager?.version !== resolution.manifest.version) {
|
|
97
|
+
if (isImplicitLatest) {
|
|
98
|
+
// Prefer the lockfile-pinned version when available — for range
|
|
99
|
+
// specs like `>=8.0.0`, the spec's lower bound understates the
|
|
100
|
+
// version that was actually installed (see #11418 review).
|
|
101
|
+
const projectCurrentVersion = await readProjectPinnedPnpmVersion(opts.rootProjectManifestDir, opts.wantedPackageManager?.version);
|
|
102
|
+
if (projectCurrentVersion != null && semver.lt(resolution.manifest.version, projectCurrentVersion)) {
|
|
103
|
+
return `The current project is set to use pnpm v${projectCurrentVersion}, which is newer than the "latest" version on the registry (v${resolution.manifest.version}). No update performed. Run "pnpm self-update latest" to downgrade.`;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
90
106
|
const { manifest, writeProjectManifest } = await readProjectManifest(opts.rootProjectManifestDir);
|
|
91
107
|
if (manifest.devEngines?.packageManager) {
|
|
92
108
|
let manifestChanged = false;
|
|
@@ -143,6 +159,9 @@ export async function handler(opts, params) {
|
|
|
143
159
|
if (resolution.manifest.version === packageManager.version) {
|
|
144
160
|
return `The currently active ${packageManager.name} v${packageManager.version} is already "${bareSpecifier}" and doesn't need an update`;
|
|
145
161
|
}
|
|
162
|
+
if (isImplicitLatest && semver.lt(resolution.manifest.version, packageManager.version)) {
|
|
163
|
+
return `The currently active ${packageManager.name} v${packageManager.version} is newer than the "latest" version on the registry (v${resolution.manifest.version}). No update performed. Run "pnpm self-update latest" to downgrade.`;
|
|
164
|
+
}
|
|
146
165
|
globalInfo(`Updating pnpm from v${packageManager.version} to v${resolution.manifest.version}...`);
|
|
147
166
|
const store = await createStoreController(opts);
|
|
148
167
|
// Resolve integrities and write env lockfile to pnpm-lock.yaml
|
|
@@ -196,4 +215,32 @@ function versionSpecFromPinned(version, pinnedVersion) {
|
|
|
196
215
|
case 'patch': return version;
|
|
197
216
|
}
|
|
198
217
|
}
|
|
218
|
+
async function readProjectPinnedPnpmVersion(rootProjectManifestDir, spec) {
|
|
219
|
+
// The env lockfile is the most accurate source for the actually-installed
|
|
220
|
+
// pnpm version when the spec is a range. Fall back to the spec's minimum
|
|
221
|
+
// version when there's no lockfile entry (e.g. exact `packageManager` pins
|
|
222
|
+
// below v12 don't write to the lockfile). Take the max of the two so we
|
|
223
|
+
// pick whichever signal is more restrictive.
|
|
224
|
+
let lockfilePinned;
|
|
225
|
+
try {
|
|
226
|
+
const envLockfile = await readEnvLockfile(rootProjectManifestDir);
|
|
227
|
+
lockfilePinned = envLockfile?.importers['.'].packageManagerDependencies?.pnpm?.version;
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
// ignore — fall through to spec min version
|
|
231
|
+
}
|
|
232
|
+
let specMin;
|
|
233
|
+
if (spec != null) {
|
|
234
|
+
try {
|
|
235
|
+
specMin = semver.minVersion(spec)?.version;
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
// invalid range — ignore
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (lockfilePinned != null && specMin != null) {
|
|
242
|
+
return semver.gt(lockfilePinned, specMin) ? lockfilePinned : specMin;
|
|
243
|
+
}
|
|
244
|
+
return lockfilePinned ?? specMin;
|
|
245
|
+
}
|
|
199
246
|
//# sourceMappingURL=selfUpdate.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/engine.pm.commands",
|
|
3
|
-
"version": "1101.1.
|
|
3
|
+
"version": "1101.1.4",
|
|
4
4
|
"description": "pnpm commands for self-updating and setting up pnpm",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -32,25 +32,26 @@
|
|
|
32
32
|
"render-help": "^2.0.0",
|
|
33
33
|
"semver": "^7.7.2",
|
|
34
34
|
"symlink-dir": "^10.0.1",
|
|
35
|
-
"@pnpm/bins.linker": "1100.0.
|
|
36
|
-
"@pnpm/building.policy": "1100.0.
|
|
37
|
-
"@pnpm/cli.meta": "1100.0.
|
|
38
|
-
"@pnpm/
|
|
39
|
-
"@pnpm/
|
|
40
|
-
"@pnpm/global.commands": "1100.0.7",
|
|
35
|
+
"@pnpm/bins.linker": "1100.0.3",
|
|
36
|
+
"@pnpm/building.policy": "1100.0.2",
|
|
37
|
+
"@pnpm/cli.meta": "1100.0.2",
|
|
38
|
+
"@pnpm/config.reader": "1101.1.4",
|
|
39
|
+
"@pnpm/deps.graph-hasher": "1100.1.2",
|
|
41
40
|
"@pnpm/error": "1100.0.0",
|
|
42
|
-
"@pnpm/
|
|
43
|
-
"@pnpm/global.
|
|
44
|
-
"@pnpm/installing.
|
|
45
|
-
"@pnpm/
|
|
46
|
-
"@pnpm/
|
|
47
|
-
"@pnpm/
|
|
48
|
-
"@pnpm/
|
|
49
|
-
"@pnpm/
|
|
50
|
-
"@pnpm/
|
|
41
|
+
"@pnpm/cli.utils": "1101.0.2",
|
|
42
|
+
"@pnpm/global.commands": "1100.0.9",
|
|
43
|
+
"@pnpm/installing.client": "1100.0.8",
|
|
44
|
+
"@pnpm/global.packages": "1100.0.2",
|
|
45
|
+
"@pnpm/installing.deps-restorer": "1101.0.4",
|
|
46
|
+
"@pnpm/installing.env-installer": "1101.0.3",
|
|
47
|
+
"@pnpm/lockfile.fs": "1100.0.4",
|
|
48
|
+
"@pnpm/lockfile.types": "1100.0.3",
|
|
49
|
+
"@pnpm/shell.path": "1100.0.1",
|
|
50
|
+
"@pnpm/store.connection-manager": "1100.0.9",
|
|
51
|
+
"@pnpm/store.controller": "1101.0.2",
|
|
51
52
|
"@pnpm/types": "1101.0.0",
|
|
52
|
-
"@pnpm/
|
|
53
|
-
"@pnpm/
|
|
53
|
+
"@pnpm/workspace.project-manifest-reader": "1100.0.3",
|
|
54
|
+
"@pnpm/resolving.npm-resolver": "1101.0.1"
|
|
54
55
|
},
|
|
55
56
|
"peerDependencies": {
|
|
56
57
|
"@pnpm/logger": ">=1001.0.0 <1002.0.0"
|
|
@@ -60,12 +61,12 @@
|
|
|
60
61
|
"@types/cross-spawn": "^6.0.6",
|
|
61
62
|
"@types/ramda": "0.31.1",
|
|
62
63
|
"@types/semver": "7.7.1",
|
|
63
|
-
"@pnpm/error": "1100.0.0",
|
|
64
|
-
"@pnpm/engine.pm.commands": "1101.1.2",
|
|
65
64
|
"@pnpm/constants": "1100.0.0",
|
|
65
|
+
"@pnpm/engine.pm.commands": "1101.1.4",
|
|
66
|
+
"@pnpm/error": "1100.0.0",
|
|
66
67
|
"@pnpm/logger": "1100.0.0",
|
|
67
|
-
"@pnpm/prepare": "1100.0.
|
|
68
|
-
"@pnpm/testing.mock-agent": "1100.0.
|
|
68
|
+
"@pnpm/prepare": "1100.0.4",
|
|
69
|
+
"@pnpm/testing.mock-agent": "1100.0.2"
|
|
69
70
|
},
|
|
70
71
|
"engines": {
|
|
71
72
|
"node": ">=22.13"
|