pnpm 12.16.1 → 12.17.0
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/CHANGELOG.md +101 -0
- package/README.md +18 -0
- package/dist/node_modules/.pnpm-workspace-state-v1.json +17 -8
- package/dist/node_modules/get-pnpm/lib/install.js +70 -15
- package/dist/node_modules/get-pnpm/lib/shadowingPnpm.js +5 -3
- package/dist/node_modules/get-pnpm/lib/undoHint.js +8 -5
- package/dist/node_modules/get-pnpm/package.json +1 -1
- package/package.json +15 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,106 @@
|
|
|
1
1
|
# pnpm
|
|
2
2
|
|
|
3
|
+
## 12.17.0
|
|
4
|
+
|
|
5
|
+
pnpm 12.17.0 adds `pnpm peers check --global`, dependency-group selectors and wildcards in `overrides`, and runtime, package manager, Cargo, and Python updates in `pnpm outdated` and `pnpm update`. It also fixes files that other users could not read in Docker images, and repeat installs that missed changes to local dependencies.
|
|
6
|
+
|
|
7
|
+
### Minor Changes
|
|
8
|
+
|
|
9
|
+
- `pnpm peers check` now accepts `--global` (`-g`) to check globally installed packages. After a global install or update, the peer dependency warning now suggests `pnpm peers check -g` [#17504](https://github.com/pnpm/pnpm/issues/17504).
|
|
10
|
+
|
|
11
|
+
- `pnpm outdated` and `pnpm update` now inspect and update package manager and runtime versions in `devEngines.packageManager`, `packageManager`, `devEngines.runtime`, `engines.runtime`, and `runtime:` dependencies. With `cargo.enabled` or `python.enabled`, `pnpm outdated` and `pnpm update` also inspect and update Cargo dependencies in `Cargo.toml` and `Cargo.lock` and Python dependencies in `pyproject.toml` and `pylock.toml`.
|
|
12
|
+
|
|
13
|
+
- `overrides` selectors now support `:prod`, `:optional`, and `:peer` pseudo-selectors that target a single dependency group. They also support `*` wildcard patterns on parent and target package names. An override with a non-range value, such as `npm:` or `file:`, no longer adds a peer dependency to `dependencies`. Removing an optional dependency with `"-"` now also removes the duplicate entry from `dependencies` [#5391](https://github.com/pnpm/pnpm/issues/5391).
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
#### Installing packages
|
|
18
|
+
|
|
19
|
+
- Files that pnpm creates in a project now get the permissions the umask gives any new file, such as `0644`. Before, several of them were readable only by the user who ran pnpm, which broke Docker images that run as a different user [#17435](https://github.com/orgs/pnpm/discussions/17435).
|
|
20
|
+
|
|
21
|
+
The fix applies to:
|
|
22
|
+
|
|
23
|
+
- `node_modules/.pnpm-workspace-state-v1.json`. A different user running `pnpm run` reinstalled the dependencies because it could not read this file.
|
|
24
|
+
- `pnpm-workspace.yaml`
|
|
25
|
+
- the files written by `pnpm deploy`
|
|
26
|
+
- patch files from `pnpm patch-commit`
|
|
27
|
+
- the lockfile restored by `pnpm dedupe --check`
|
|
28
|
+
- the Cargo and Python files that pnpm writes
|
|
29
|
+
|
|
30
|
+
When pnpm edits an existing file, the file keeps its permissions.
|
|
31
|
+
|
|
32
|
+
- `pnpm install` no longer writes broken dependency links when the project's `node_modules` is a symlink to another directory, such as another project's `node_modules`. The install reported success, but the links it wrote did not resolve [#17448](https://github.com/pnpm/pnpm/issues/17448).
|
|
33
|
+
|
|
34
|
+
- Commands installed with `pnpm add --global` now find the dependencies that pnpm hoists for their package. A package that loads a dependency it does not declare, such as a native addon's platform-specific package, failed with "Cannot find module". Reinstall such a package with `pnpm add --global` to update its existing command [#17503](https://github.com/pnpm/pnpm/issues/17503).
|
|
35
|
+
|
|
36
|
+
- When pnpm switches to the version a project pins, it now installs that version's native binary for the current host, even if the project's `supportedArchitectures` excludes the host. Before, pnpm could not use the pinned version and kept running the installed one. pnpm also repairs a pinned version that an earlier install left without the host's binary.
|
|
37
|
+
|
|
38
|
+
- With the global virtual store, a change to a dependency of one package in a dependency cycle now gives every package in that cycle a new directory. Before, the other packages kept their directories and still linked the old copy of the changed package, so the project could load two copies of it [#17466](https://github.com/pnpm/pnpm/issues/17466).
|
|
39
|
+
|
|
40
|
+
Packages in a dependency cycle, and packages that depend on one, move to new global virtual store directories once after this update. Those that run a build miss the side-effects cache once.
|
|
41
|
+
|
|
42
|
+
- With `nodeLinker: hoisted`, when two workspace projects need the same package version and it cannot be hoisted to the root, each project now keeps the copy installed in its own `node_modules`. Build scripts run in each of these copies. Before, the second project's copy was replaced with a symlink to the first project's, so every repeat install imported it again [#17498](https://github.com/pnpm/pnpm/issues/17498).
|
|
43
|
+
|
|
44
|
+
- The Node.js `latest` selector now chooses the newest stable release [#17490](https://github.com/pnpm/pnpm/issues/17490).
|
|
45
|
+
|
|
46
|
+
- Hardlinking from the store now stats each store file once per install. Since pnpm 12.8.0, a store file was stat'ed again for every package that links it. On an offline install of a large workspace, that added up to 15% system CPU [#17500](https://github.com/pnpm/pnpm/issues/17500).
|
|
47
|
+
|
|
48
|
+
#### Repeat installs and local dependencies
|
|
49
|
+
|
|
50
|
+
- `pnpm install --frozen-lockfile` no longer reports an outdated lockfile right after the install that wrote it. This happened when a pnpmfile `readPackage` hook or `packageExtensions` changed the dependencies or peer dependencies of a local directory dependency outside the workspace projects. It affected a `file:` dependency, an injected `workspace:../dir` dependency outside the workspace patterns, and an injected workspace package left out by `--filter` [#17447](https://github.com/pnpm/pnpm/issues/17447) [#17473](https://github.com/pnpm/pnpm/issues/17473).
|
|
51
|
+
|
|
52
|
+
A repeat `pnpm install` now takes the fast path when `ignoredOptionalDependencies` removes an optional dependency of a `file:` directory dependency. It used to resolve again on every run.
|
|
53
|
+
|
|
54
|
+
- `pnpm install` now resolves again after an edit to an injected `workspace:../dir` dependency outside the workspace patterns under a shared lockfile. It used to keep the lockfile unchanged. The next `pnpm install --frozen-lockfile` then failed [#17476](https://github.com/pnpm/pnpm/issues/17476).
|
|
55
|
+
|
|
56
|
+
- `pnpm install` now resolves a local directory again after its `package.json` changes when an override or a package extension adds it to the dependencies of a registry package. `pnpm install --frozen-lockfile` fails on a lockfile that still records the old dependencies of such a directory [#17486](https://github.com/pnpm/pnpm/issues/17486).
|
|
57
|
+
|
|
58
|
+
- With `injectWorkspacePackages` and per-project lockfiles, `pnpm install` now updates a project's lockfile when a local tarball that an injected workspace project depends on is replaced. The project's lockfile kept the old version and integrity before.
|
|
59
|
+
|
|
60
|
+
- `pnpm install` now detects a change to a local tarball or directory that only a pnpmfile `readPackage` hook depends on. A repeat install reported "Already up to date" and kept the old contents before [pnpm/tasks#227](https://github.com/pnpm/tasks/issues/227).
|
|
61
|
+
|
|
62
|
+
- `pnpm install` now relinks a `workspace:` or `link:` dependency whose link was deleted from `node_modules`. It used to report "Already up to date" and leave the link missing [#17485](https://github.com/pnpm/pnpm/issues/17485).
|
|
63
|
+
|
|
64
|
+
- A repeat `pnpm install` reports "Already up to date" again when a pnpmfile `readPackage` hook changes the dependencies of a workspace project. Since 12.15.0, every such install ran in full [#17468](https://github.com/pnpm/pnpm/issues/17468).
|
|
65
|
+
|
|
66
|
+
After an edit to a project's `package.json`, `pnpm install` and `verifyDepsBeforeRun` now run the pnpmfile's `readPackage` hook on the edited manifest before comparing it with the lockfile. They could report the project up to date when the hook rewrote the edited dependency to a specifier the lockfile did not record.
|
|
67
|
+
|
|
68
|
+
#### Adding and updating dependencies
|
|
69
|
+
|
|
70
|
+
- `pnpm update --latest` with package selectors now updates the dependencies of the selected packages within their declared ranges. Excluded packages and their dependencies keep their locked versions [#17444](https://github.com/pnpm/pnpm/issues/17444).
|
|
71
|
+
|
|
72
|
+
- `pnpm add <pkg>@<tag>` now uses a catalog entry set to that same dist-tag. The dependency is saved as `catalog:` and the entry stays as written [pnpm/tasks#225](https://github.com/pnpm/tasks/issues/225).
|
|
73
|
+
|
|
74
|
+
When `pnpm add` adds a new dist-tag such as `vue@legacy` to a catalog, the catalog entry records the exact version the tag points to. The same applies to a dependency added without a version when the `tag` setting names a dist-tag other than `latest`.
|
|
75
|
+
|
|
76
|
+
- `pnpm add` now saves the resolved version range of an npm alias. For example, `pnpm add v2@npm:vue` and `pnpm add v2@npm:vue@^3.0.0` both save `npm:vue@^3.5.13`.
|
|
77
|
+
|
|
78
|
+
#### Running scripts and commands
|
|
79
|
+
|
|
80
|
+
- Programs that a script or `pnpm exec` command leaves running, such as a browser opened by the `open` package, now outlive pnpm exactly when they would outlive the command run without pnpm. Before, on Windows, a failed command, `Ctrl+C`, or a closed terminal ended all of them. pnpm still ends them when it is killed or crashes.
|
|
81
|
+
|
|
82
|
+
When a recursive or parallel run bails, the scripts still running now receive `SIGTERM` on Unix and are killed only if they are still running two seconds later. On Windows, everything those scripts started is ended, including detached processes whose parent has already exited. Before, a bail killed them at once [#17465](https://github.com/pnpm/pnpm/issues/17465).
|
|
83
|
+
|
|
84
|
+
- On Windows, the shell shim of a `.cmd` or `.bat` bin now runs it under Git Bash when MSYS argument conversion is off, such as with `MSYS_NO_PATHCONV=1` or `MSYS2_ARG_CONV_EXCL='*'`. The shim used to start an interactive cmd.exe prompt [#17480](https://github.com/pnpm/pnpm/issues/17480).
|
|
85
|
+
|
|
86
|
+
- `pnx` and `pnpm create` now run the command in the directory selected by `--dir` or `--workspace-root`. Without either flag, the command still runs in the directory pnpm was started in.
|
|
87
|
+
|
|
88
|
+
- `pnpm --env-file` now reads files the way `node --env-file` does. Values are taken as written, so `$VAR` is no longer expanded and Windows paths such as `C:\Users\me` load unchanged. A file is no longer rejected for its contents.
|
|
89
|
+
|
|
90
|
+
#### Settings and messages
|
|
91
|
+
|
|
92
|
+
- `pnpm version` no longer creates a git commit and tag when `gitTagVersion` is set to `false` [#17460](https://github.com/pnpm/pnpm/issues/17460).
|
|
93
|
+
|
|
94
|
+
- `pnpm publish` now reads the `publishBranch` setting from `pnpm-workspace.yaml` and from `PNPM_CONFIG_PUBLISH_BRANCH`. The `--publish-branch` flag overrides it.
|
|
95
|
+
|
|
96
|
+
- `pnpm` now accepts `--strict-ssl` and `--local-address <ip>` on the command line.
|
|
97
|
+
|
|
98
|
+
- `pnpm doctor` uses a 15-second timeout when checking registry connectivity.
|
|
99
|
+
|
|
100
|
+
- `pnpm-workspace.yaml` parse errors now report `ERR_PNPM_INVALID_SETTING`.
|
|
101
|
+
|
|
102
|
+
- The error for a dependency with an invalid name in a project's manifest now names the project's directory. It used to say only "The current package", which did not tell which workspace project to fix [#17475](https://github.com/pnpm/pnpm/issues/17475).
|
|
103
|
+
|
|
3
104
|
## 12.16.1
|
|
4
105
|
|
|
5
106
|
This release fixes `pnpm install` hanging on a cold store in workspaces that install Cargo crates, and `pnpm pack` shipping a file that `files` excludes by name.
|
package/README.md
CHANGED
|
@@ -65,6 +65,15 @@ To quote the [Rush](https://rushjs.io/) team:
|
|
|
65
65
|
</picture>
|
|
66
66
|
</a>
|
|
67
67
|
</td>
|
|
68
|
+
<td align="center" valign="middle">
|
|
69
|
+
<a href="https://www.cloudflare.com/?utm_source=pnpm&utm_medium=readme" target="_blank" rel="noopener noreferrer">
|
|
70
|
+
<picture>
|
|
71
|
+
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/cloudflare.svg" />
|
|
72
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/cloudflare_light.svg" />
|
|
73
|
+
<img src="https://pnpm.io/img/users/cloudflare.svg" width="160" alt="Cloudflare" />
|
|
74
|
+
</picture>
|
|
75
|
+
</a>
|
|
76
|
+
</td>
|
|
68
77
|
</tr>
|
|
69
78
|
</tbody>
|
|
70
79
|
</table>
|
|
@@ -138,6 +147,15 @@ To quote the [Rush](https://rushjs.io/) team:
|
|
|
138
147
|
<td align="center" valign="middle">
|
|
139
148
|
<a href="https://latitude.so/?utm_source=pnpm&utm_medium=readme" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/latitude.svg" width="160" alt="Latitude"></a>
|
|
140
149
|
</td>
|
|
150
|
+
<td align="center" valign="middle">
|
|
151
|
+
<a href="https://syntax.fm/?utm_source=pnpm&utm_medium=readme" target="_blank" rel="noopener noreferrer">
|
|
152
|
+
<picture>
|
|
153
|
+
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/syntaxfm.svg" />
|
|
154
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/syntaxfm_light.svg" />
|
|
155
|
+
<img src="https://pnpm.io/img/users/syntaxfm.svg" width="90" alt="Syntax" />
|
|
156
|
+
</picture>
|
|
157
|
+
</a>
|
|
158
|
+
</td>
|
|
141
159
|
</tr>
|
|
142
160
|
</tbody>
|
|
143
161
|
</table>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"lastValidatedTimestamp":
|
|
2
|
+
"lastValidatedTimestamp": 1793364144621,
|
|
3
3
|
"projects": {
|
|
4
4
|
"/home/runner/_work/pnpm/pnpm/pnpm/npm/pnpm/temp-deploy": {
|
|
5
5
|
"name": "pacquet",
|
|
6
|
-
"version": "12.
|
|
6
|
+
"version": "12.17.0",
|
|
7
7
|
"hasModulesDir": true
|
|
8
8
|
}
|
|
9
9
|
},
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"autoInstallPeers": true,
|
|
23
23
|
"catalogs": {},
|
|
24
|
+
"dangerouslyAllowAllBuilds": false,
|
|
24
25
|
"dedupeDirectDeps": false,
|
|
25
26
|
"dedupeInjectedDeps": false,
|
|
26
27
|
"dedupePeerDependents": false,
|
|
@@ -82,6 +83,10 @@
|
|
|
82
83
|
"preferWorkspacePackages": false,
|
|
83
84
|
"production": true,
|
|
84
85
|
"publicHoistPattern": [],
|
|
86
|
+
"registryRoutes": {
|
|
87
|
+
"@jsr": "https://npm.jsr.io/",
|
|
88
|
+
"@pnpm": "https://registry.npmjs.org/"
|
|
89
|
+
},
|
|
85
90
|
"trustPolicy": "no-downgrade",
|
|
86
91
|
"trustPolicyExclude": [
|
|
87
92
|
"@pnpm/*",
|
|
@@ -91,6 +96,7 @@
|
|
|
91
96
|
"undici-types@6.21.0"
|
|
92
97
|
],
|
|
93
98
|
"trustPolicyIgnoreAfter": 10080,
|
|
99
|
+
"virtualStoreDirMaxLength": 120,
|
|
94
100
|
"workspacePackagePatterns": [
|
|
95
101
|
".meta-updater",
|
|
96
102
|
"pnpm11/__typecheck__",
|
|
@@ -162,24 +168,27 @@
|
|
|
162
168
|
]
|
|
163
169
|
},
|
|
164
170
|
"validation": {
|
|
165
|
-
"recordedAtNs":
|
|
171
|
+
"recordedAtNs": 1793364144621578968,
|
|
166
172
|
"files": {
|
|
167
173
|
"/home/runner/_work/pnpm/pnpm/pnpm/npm/pnpm/temp-deploy/../../../../.config/pnpm/patches/graceful-fs@4.2.11.patch": {
|
|
168
|
-
"mtimeNs":
|
|
169
|
-
"ctimeNs":
|
|
174
|
+
"mtimeNs": 1793364126597573401,
|
|
175
|
+
"ctimeNs": 1793364126597573401,
|
|
170
176
|
"size": 671,
|
|
171
177
|
"digest": "68ebc232025360cb3dcd3081f4067f4e"
|
|
172
178
|
},
|
|
173
179
|
"/home/runner/_work/pnpm/pnpm/pnpm/npm/pnpm/temp-deploy/pnpm-lock.yaml": {
|
|
174
|
-
"mtimeNs":
|
|
175
|
-
"ctimeNs":
|
|
180
|
+
"mtimeNs": 1793364144445578912,
|
|
181
|
+
"ctimeNs": 1793364144445578912,
|
|
176
182
|
"size": 6001,
|
|
177
183
|
"digest": "b251eb0d29c262f40cbf984a99f53fb8"
|
|
178
184
|
}
|
|
179
185
|
},
|
|
180
186
|
"lockfile": "b251eb0d29c262f40cbf984a99f53fb8",
|
|
181
187
|
"manifests": {
|
|
182
|
-
".": "
|
|
188
|
+
".": "2d48f551c25a522720cb8473e07df6a2"
|
|
189
|
+
},
|
|
190
|
+
"workspaceBins": {
|
|
191
|
+
".": "fbddc193afab8e95acb4f0d48b0ca9c9"
|
|
183
192
|
}
|
|
184
193
|
}
|
|
185
194
|
}
|
|
@@ -2,6 +2,7 @@ import { spawnSync } from 'node:child_process';
|
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
+
import semver from 'semver';
|
|
5
6
|
import { extractTarball } from './extractTarball.js';
|
|
6
7
|
import { registryConfigFromEnv } from './npmConfig.js';
|
|
7
8
|
import { isMusl, platformPackageName } from './platformPackageName.js';
|
|
@@ -23,7 +24,9 @@ const UNPACK_DIR = '.unpack';
|
|
|
23
24
|
function wrapperPackageName(major) {
|
|
24
25
|
return major >= 12 ? CLI_PKG_NAME : '@pnpm/exe';
|
|
25
26
|
}
|
|
26
|
-
|
|
27
|
+
/** The first pnpm whose `pnpm setup` has `--no-modify-path`. */
|
|
28
|
+
const NO_MODIFY_PATH_SINCE = '12.16.0';
|
|
29
|
+
const USAGE = `Usage: npx get-pnpm [--no-modify-path] [version]
|
|
27
30
|
|
|
28
31
|
Installs pnpm as a standalone executable and adds it to your PATH.
|
|
29
32
|
|
|
@@ -39,8 +42,15 @@ Arguments:
|
|
|
39
42
|
range resolves to the version pnpm-lock.yaml records
|
|
40
43
|
while that is still in range.
|
|
41
44
|
|
|
45
|
+
Options:
|
|
46
|
+
--no-modify-path Install pnpm without adding it to PATH: leave the shell
|
|
47
|
+
config file and the Windows registry unchanged, and print
|
|
48
|
+
the lines to add instead. Needs pnpm ${NO_MODIFY_PATH_SINCE} or
|
|
49
|
+
newer.
|
|
50
|
+
|
|
42
51
|
Environment variables:
|
|
43
52
|
PNPM_VERSION Version to install when no argument is given.
|
|
53
|
+
PNPM_NO_MODIFY_PATH Set to 1 for the same as --no-modify-path.
|
|
44
54
|
PNPM_HOME Directory to install pnpm into.
|
|
45
55
|
npm_config_registry Registry to download pnpm from.
|
|
46
56
|
npm_config_*:_authToken
|
|
@@ -56,11 +66,28 @@ Environment variables:
|
|
|
56
66
|
Node 24.14 or later.
|
|
57
67
|
`;
|
|
58
68
|
export async function runCli(argv) {
|
|
69
|
+
const args = parseCliArgs(argv, process.env);
|
|
70
|
+
if (args.help) {
|
|
71
|
+
console.log(USAGE);
|
|
72
|
+
return 0;
|
|
73
|
+
}
|
|
74
|
+
const registryConfig = registryConfigFromEnv();
|
|
75
|
+
return installPnpm({
|
|
76
|
+
versionSpec: args.version ?? process.env.PNPM_VERSION ?? projectVersionSpec(process.cwd()) ?? 'latest',
|
|
77
|
+
modifyPath: args.modifyPath,
|
|
78
|
+
...registryConfig,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/** The command line, with `PNPM_NO_MODIFY_PATH` as the default of `--no-modify-path`. */
|
|
82
|
+
export function parseCliArgs(argv, env) {
|
|
59
83
|
const positional = [];
|
|
84
|
+
let modifyPath = !isEnabled(env.PNPM_NO_MODIFY_PATH);
|
|
60
85
|
for (const arg of argv) {
|
|
61
|
-
if (arg === '--help' || arg === '-h')
|
|
62
|
-
|
|
63
|
-
|
|
86
|
+
if (arg === '--help' || arg === '-h')
|
|
87
|
+
return { help: true, modifyPath };
|
|
88
|
+
if (arg === '--no-modify-path') {
|
|
89
|
+
modifyPath = false;
|
|
90
|
+
continue;
|
|
64
91
|
}
|
|
65
92
|
if (arg.startsWith('-')) {
|
|
66
93
|
throw new Error(`Unknown option "${arg}".\n\n${USAGE}`);
|
|
@@ -70,11 +97,11 @@ export async function runCli(argv) {
|
|
|
70
97
|
if (positional.length > 1) {
|
|
71
98
|
throw new Error(`Expected at most one version, got ${positional.length}.\n\n${USAGE}`);
|
|
72
99
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
100
|
+
return { help: false, version: positional[0], modifyPath };
|
|
101
|
+
}
|
|
102
|
+
/** Whether an on/off environment variable is on: set to anything but "", "0", or "false". */
|
|
103
|
+
function isEnabled(value) {
|
|
104
|
+
return value != null && value !== '' && value !== '0' && value.toLowerCase() !== 'false';
|
|
78
105
|
}
|
|
79
106
|
/** The version `readProjectPin` finds for `dir`, saying where it comes from. */
|
|
80
107
|
function projectVersionSpec(dir) {
|
|
@@ -96,6 +123,10 @@ function projectVersionSpec(dir) {
|
|
|
96
123
|
* https://get.pnpm.io/install.sh downloads — the executable next to its `dist/`
|
|
97
124
|
* tree — because `pnpm setup` installs that directory as-is.
|
|
98
125
|
*
|
|
126
|
+
* With `modifyPath: false`, `pnpm setup --no-modify-path` leaves the shell
|
|
127
|
+
* config and the Windows registry alone. A pnpm whose setup lacks that option
|
|
128
|
+
* is refused before setup runs.
|
|
129
|
+
*
|
|
99
130
|
* @returns the exit code of `pnpm setup`.
|
|
100
131
|
*/
|
|
101
132
|
export async function installPnpm(opts) {
|
|
@@ -116,13 +147,19 @@ export async function installPnpm(opts) {
|
|
|
116
147
|
process.once(signal, onSignal);
|
|
117
148
|
}
|
|
118
149
|
try {
|
|
119
|
-
const { binPath } = await downloadPnpm({ ...opts, dest: tmpDir });
|
|
120
|
-
const
|
|
150
|
+
const { version, binPath } = await downloadPnpm({ ...opts, dest: tmpDir });
|
|
151
|
+
const modifyPath = opts.modifyPath ?? true;
|
|
152
|
+
const setupArgs = [...setupCommand(version), '--force'];
|
|
153
|
+
if (!modifyPath) {
|
|
154
|
+
assertSetupCanLeavePathAlone(version);
|
|
155
|
+
setupArgs.push('--no-modify-path');
|
|
156
|
+
}
|
|
157
|
+
const { error, status } = spawnSync(binPath, setupArgs, { stdio: 'inherit' });
|
|
121
158
|
if (error != null)
|
|
122
159
|
throw error;
|
|
123
160
|
if (status === 0) {
|
|
124
|
-
console.log(renderUndoHint(pnpmHomeDir()));
|
|
125
|
-
warnIfPnpmIsShadowed();
|
|
161
|
+
console.log(renderUndoHint(pnpmHomeDir(), process.platform, { modifiedPath: modifyPath }));
|
|
162
|
+
warnIfPnpmIsShadowed({ modifiedPath: modifyPath });
|
|
126
163
|
}
|
|
127
164
|
return status ?? 1;
|
|
128
165
|
}
|
|
@@ -133,16 +170,34 @@ export async function installPnpm(opts) {
|
|
|
133
170
|
removeTmpDir();
|
|
134
171
|
}
|
|
135
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* The versions whose `pm` prefix forces a built-in command. pnpm 12.0.0 was
|
|
175
|
+
* released without it.
|
|
176
|
+
*/
|
|
177
|
+
const PM_PREFIX_VERSIONS = '>=11.0.0-beta.6 <12.0.0-0 || >=12.1.0';
|
|
178
|
+
/**
|
|
179
|
+
* How to invoke the built-in `pnpm setup` of pnpm `version`. From pnpm 11, a
|
|
180
|
+
* `setup` script in the project the installer runs from can replace the
|
|
181
|
+
* built-in unless the `pm` prefix forces it.
|
|
182
|
+
*/
|
|
183
|
+
export function setupCommand(version) {
|
|
184
|
+
return semver.satisfies(version, PM_PREFIX_VERSIONS, { includePrerelease: true }) ? ['pm', 'setup'] : ['setup'];
|
|
185
|
+
}
|
|
186
|
+
function assertSetupCanLeavePathAlone(version) {
|
|
187
|
+
if (semver.lt(version, NO_MODIFY_PATH_SINCE)) {
|
|
188
|
+
throw new Error(`pnpm ${version} cannot be installed without adding it to PATH: --no-modify-path needs pnpm ${NO_MODIFY_PATH_SINCE} or newer. Install a newer pnpm, or leave out --no-modify-path.`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
136
191
|
/**
|
|
137
192
|
* Says so when the pnpm `pnpm setup` just installed is not the one PATH
|
|
138
193
|
* resolves, or the success above is the last thing the person reads before
|
|
139
194
|
* `pnpm --version` prints the old version again.
|
|
140
195
|
*/
|
|
141
|
-
function warnIfPnpmIsShadowed() {
|
|
196
|
+
function warnIfPnpmIsShadowed(opts) {
|
|
142
197
|
const pnpmHome = pnpmHomeDir();
|
|
143
198
|
const shadowing = findShadowingPnpm(pnpmHome, { pathEnv: readPathEnv(process.env) });
|
|
144
199
|
if (shadowing != null) {
|
|
145
|
-
console.error(renderShadowingPnpmWarning(shadowing, pnpmHome));
|
|
200
|
+
console.error(renderShadowingPnpmWarning(shadowing, pnpmHome, opts));
|
|
146
201
|
}
|
|
147
202
|
}
|
|
148
203
|
/** Windows spells the variable `Path`, and the environment is case-insensitive there. */
|
|
@@ -65,9 +65,10 @@ export function findShadowingPnpm(pnpmHome, opts) {
|
|
|
65
65
|
}
|
|
66
66
|
/**
|
|
67
67
|
* The warning to print once `pnpm setup` installed under `pnpmHome` and
|
|
68
|
-
* `shadowing` still answers to `pnpm`.
|
|
68
|
+
* `shadowing` still answers to `pnpm`. Without `modifiedPath`, setup left the
|
|
69
|
+
* shell config alone, so no new shell adds `$PNPM_HOME/bin` by itself.
|
|
69
70
|
*/
|
|
70
|
-
export function renderShadowingPnpmWarning(shadowing, pnpmHome) {
|
|
71
|
+
export function renderShadowingPnpmWarning(shadowing, pnpmHome, { modifiedPath = true } = {}) {
|
|
71
72
|
const bin = path.join(pnpmHome, 'bin');
|
|
72
73
|
const origin = ORIGIN_DESCRIPTIONS[shadowing.origin];
|
|
73
74
|
const reorder = `move ${bin} ahead of ${path.dirname(shadowing.executable)} in PATH`;
|
|
@@ -78,8 +79,9 @@ export function renderShadowingPnpmWarning(shadowing, pnpmHome) {
|
|
|
78
79
|
`Your shell keeps running that pnpm, not the one pnpm installed to ${bin}.\n` +
|
|
79
80
|
`To finish switching, ${fix}.`;
|
|
80
81
|
}
|
|
82
|
+
const when = modifiedPath ? 'Once a new shell adds it' : 'When you add it';
|
|
81
83
|
return `Warning: "pnpm" on PATH is ${shadowing.executable} (${origin}), and ${bin} is not on PATH yet.\n` +
|
|
82
|
-
|
|
84
|
+
`${when}, it has to come first: ${fix}.`;
|
|
83
85
|
}
|
|
84
86
|
export function detectInstallOrigin(executable) {
|
|
85
87
|
return originFromPath(realpathOrSelf(executable)) ??
|
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
* How to take back what `pnpm setup` just did under `pnpmHome`, printed once
|
|
3
3
|
* it succeeds. `pnpm setup` names the shell config file it changed and prints
|
|
4
4
|
* the lines it added, so the hint points back at that output rather than
|
|
5
|
-
* guessing the file again.
|
|
5
|
+
* guessing the file again. Without `modifiedPath`, setup changed nothing but
|
|
6
|
+
* `pnpmHome`.
|
|
6
7
|
*/
|
|
7
|
-
export function renderUndoHint(pnpmHome, platform = process.platform) {
|
|
8
|
-
const undo =
|
|
9
|
-
? `delete ${pnpmHome}
|
|
10
|
-
:
|
|
8
|
+
export function renderUndoHint(pnpmHome, platform = process.platform, { modifiedPath = true } = {}) {
|
|
9
|
+
const undo = !modifiedPath
|
|
10
|
+
? `delete ${pnpmHome}.`
|
|
11
|
+
: platform === 'win32'
|
|
12
|
+
? `delete ${pnpmHome}, then remove the PNPM_HOME variable and the Path entry pnpm setup added from your user environment variables.`
|
|
13
|
+
: `delete ${pnpmHome} and the lines pnpm setup added to the shell config file named above.`;
|
|
11
14
|
return `To uninstall, ${undo}\nSee https://pnpm.io/uninstall`;
|
|
12
15
|
}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"./dist/node_modules/node-gyp/gyp/gyp"
|
|
10
10
|
]
|
|
11
11
|
},
|
|
12
|
-
"version": "12.
|
|
12
|
+
"version": "12.17.0",
|
|
13
13
|
"description": "Fast, disk space efficient package manager",
|
|
14
14
|
"keywords": [
|
|
15
15
|
"pnpm",
|
|
@@ -46,20 +46,20 @@
|
|
|
46
46
|
"THIRD-PARTY-NOTICES.md"
|
|
47
47
|
],
|
|
48
48
|
"optionalDependencies": {
|
|
49
|
-
"@pnpm/exe.win32-x64": "12.
|
|
50
|
-
"@pnpm/exe.win32-arm64": "12.
|
|
51
|
-
"@pnpm/exe.darwin-x64": "12.
|
|
52
|
-
"@pnpm/exe.darwin-arm64": "12.
|
|
53
|
-
"@pnpm/exe.linux-x64": "12.
|
|
54
|
-
"@pnpm/exe.linux-arm64": "12.
|
|
55
|
-
"@pnpm/exe.linux-riscv64": "12.
|
|
56
|
-
"@pnpm/exe.linux-ppc64": "12.
|
|
57
|
-
"@pnpm/exe.linux-s390x": "12.
|
|
58
|
-
"@pnpm/exe.linux-x64-musl": "12.
|
|
59
|
-
"@pnpm/exe.linux-arm64-musl": "12.
|
|
60
|
-
"@pnpm/exe.freebsd-x64": "12.
|
|
61
|
-
"@pnpm/exe.android-arm64": "12.
|
|
62
|
-
"@pnpm/exe.android-x64": "12.
|
|
49
|
+
"@pnpm/exe.win32-x64": "12.17.0",
|
|
50
|
+
"@pnpm/exe.win32-arm64": "12.17.0",
|
|
51
|
+
"@pnpm/exe.darwin-x64": "12.17.0",
|
|
52
|
+
"@pnpm/exe.darwin-arm64": "12.17.0",
|
|
53
|
+
"@pnpm/exe.linux-x64": "12.17.0",
|
|
54
|
+
"@pnpm/exe.linux-arm64": "12.17.0",
|
|
55
|
+
"@pnpm/exe.linux-riscv64": "12.17.0",
|
|
56
|
+
"@pnpm/exe.linux-ppc64": "12.17.0",
|
|
57
|
+
"@pnpm/exe.linux-s390x": "12.17.0",
|
|
58
|
+
"@pnpm/exe.linux-x64-musl": "12.17.0",
|
|
59
|
+
"@pnpm/exe.linux-arm64-musl": "12.17.0",
|
|
60
|
+
"@pnpm/exe.freebsd-x64": "12.17.0",
|
|
61
|
+
"@pnpm/exe.android-arm64": "12.17.0",
|
|
62
|
+
"@pnpm/exe.android-x64": "12.17.0"
|
|
63
63
|
},
|
|
64
64
|
"scripts": {
|
|
65
65
|
"preinstall": "node install.js",
|