@pnpm/global.packages 1100.0.9 → 1100.0.11
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 +157 -0
- package/lib/globalPackageDir.js +20 -4
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/scanGlobalPackages.d.ts +1 -0
- package/lib/scanGlobalPackages.js +42 -2
- package/package.json +7 -7
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# @pnpm/global.packages
|
|
2
|
+
|
|
3
|
+
## 1100.0.11
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies:
|
|
8
|
+
- @pnpm/bins.resolver@1100.0.9
|
|
9
|
+
- @pnpm/pkg-manifest.reader@1100.0.10
|
|
10
|
+
- @pnpm/types@1101.4.0
|
|
11
|
+
|
|
12
|
+
## 1100.0.10
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- be6505a: Hardened global package management:
|
|
17
|
+
|
|
18
|
+
- On Windows, removing or updating a global package now also cleans up the `node.exe` flavor of a bin, so a stale `node.exe` no longer survives on `PATH` after uninstall, and a new global install no longer silently overwrites an existing `node.exe`.
|
|
19
|
+
- `pnpm add -g pnpm@<version>` (and `@pnpm/exe@<version>`) is now rejected like the bare `pnpm` form, pointing to `pnpm self-update`.
|
|
20
|
+
- Dependency aliases read from a global package's manifest are validated before being joined onto `node_modules` paths, preventing a tampered manifest from escaping the install directory.
|
|
21
|
+
- Each global install group is created in its own freshly-made directory (no longer reusing a colliding or pre-existing path).
|
|
22
|
+
- Removing or updating a global package no longer unlinks a bin that belongs to a different globally installed package.
|
|
23
|
+
- @pnpm/crypto.hash@1100.0.1
|
|
24
|
+
|
|
25
|
+
## 1100.0.9
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- @pnpm/pkg-manifest.reader@1100.0.9
|
|
30
|
+
- @pnpm/crypto.hash@1100.0.1
|
|
31
|
+
|
|
32
|
+
## 1100.0.8
|
|
33
|
+
|
|
34
|
+
### Patch Changes
|
|
35
|
+
|
|
36
|
+
- a31faa7: Updated dependency ranges. Notably:
|
|
37
|
+
|
|
38
|
+
- `@pnpm/logger` peer dependency range moved to `^1100.0.0`.
|
|
39
|
+
- `msgpackr` 1.11.8 → 2.0.4 (store index files remain byte-compatible in both directions).
|
|
40
|
+
- `open` ^7.4.2 → ^11.0.0, `memoize` ^10 → ^11, `cli-truncate` ^5 → ^6, `pidtree` ^0.6 → ^1.
|
|
41
|
+
- `@yarnpkg/core` 4.5.0 → 4.8.0, `@rushstack/worker-pool` 0.7.7 → 0.7.18, `@cyclonedx/cyclonedx-library` 10.0.0 → 10.1.0, `@pnpm/config.nerf-dart` ^1 → ^2, `@pnpm/log.group` 3.0.2 → 4.0.1, `@pnpm/util.lex-comparator` ^3 → ^4.
|
|
42
|
+
|
|
43
|
+
- Updated dependencies [681b593]
|
|
44
|
+
- @pnpm/types@1101.3.2
|
|
45
|
+
- @pnpm/bins.resolver@1100.0.8
|
|
46
|
+
- @pnpm/pkg-manifest.reader@1100.0.8
|
|
47
|
+
- @pnpm/crypto.hash@1100.0.1
|
|
48
|
+
|
|
49
|
+
## 1100.0.7
|
|
50
|
+
|
|
51
|
+
### Patch Changes
|
|
52
|
+
|
|
53
|
+
- Updated dependencies [230df57]
|
|
54
|
+
- Updated dependencies [bf1b731]
|
|
55
|
+
- @pnpm/bins.resolver@1100.0.7
|
|
56
|
+
- @pnpm/types@1101.3.1
|
|
57
|
+
- @pnpm/pkg-manifest.reader@1100.0.7
|
|
58
|
+
- @pnpm/crypto.hash@1100.0.1
|
|
59
|
+
|
|
60
|
+
## 1100.0.6
|
|
61
|
+
|
|
62
|
+
### Patch Changes
|
|
63
|
+
|
|
64
|
+
- Updated dependencies [a017bf3]
|
|
65
|
+
- @pnpm/types@1101.3.0
|
|
66
|
+
- @pnpm/bins.resolver@1100.0.6
|
|
67
|
+
- @pnpm/pkg-manifest.reader@1100.0.6
|
|
68
|
+
- @pnpm/crypto.hash@1100.0.1
|
|
69
|
+
|
|
70
|
+
## 1100.0.5
|
|
71
|
+
|
|
72
|
+
### Patch Changes
|
|
73
|
+
|
|
74
|
+
- Updated dependencies [35d2355]
|
|
75
|
+
- @pnpm/types@1101.2.0
|
|
76
|
+
- @pnpm/bins.resolver@1100.0.5
|
|
77
|
+
- @pnpm/pkg-manifest.reader@1100.0.5
|
|
78
|
+
- @pnpm/crypto.hash@1100.0.1
|
|
79
|
+
|
|
80
|
+
## 1100.0.4
|
|
81
|
+
|
|
82
|
+
### Patch Changes
|
|
83
|
+
|
|
84
|
+
- Updated dependencies [64afc92]
|
|
85
|
+
- @pnpm/types@1101.1.1
|
|
86
|
+
- @pnpm/bins.resolver@1100.0.4
|
|
87
|
+
- @pnpm/pkg-manifest.reader@1100.0.4
|
|
88
|
+
- @pnpm/crypto.hash@1100.0.1
|
|
89
|
+
|
|
90
|
+
## 1100.0.3
|
|
91
|
+
|
|
92
|
+
### Patch Changes
|
|
93
|
+
|
|
94
|
+
- Updated dependencies [b61e268]
|
|
95
|
+
- @pnpm/types@1101.1.0
|
|
96
|
+
- @pnpm/bins.resolver@1100.0.3
|
|
97
|
+
- @pnpm/pkg-manifest.reader@1100.0.3
|
|
98
|
+
- @pnpm/crypto.hash@1100.0.1
|
|
99
|
+
|
|
100
|
+
## 1100.0.2
|
|
101
|
+
|
|
102
|
+
### Patch Changes
|
|
103
|
+
|
|
104
|
+
- Updated dependencies [184ce26]
|
|
105
|
+
- @pnpm/pkg-manifest.reader@1100.0.2
|
|
106
|
+
- @pnpm/bins.resolver@1100.0.2
|
|
107
|
+
- @pnpm/crypto.hash@1100.0.1
|
|
108
|
+
|
|
109
|
+
## 1100.0.1
|
|
110
|
+
|
|
111
|
+
### Patch Changes
|
|
112
|
+
|
|
113
|
+
- Updated dependencies [ff28085]
|
|
114
|
+
- @pnpm/types@1101.0.0
|
|
115
|
+
- @pnpm/bins.resolver@1100.0.1
|
|
116
|
+
- @pnpm/pkg-manifest.reader@1100.0.1
|
|
117
|
+
- @pnpm/crypto.hash@1100.0.0
|
|
118
|
+
|
|
119
|
+
## 1000.0.0
|
|
120
|
+
|
|
121
|
+
### Minor Changes
|
|
122
|
+
|
|
123
|
+
- fd511e4: Isolated global packages. Each globally installed package (or group of packages installed together) now gets its own isolated installation directory with its own `package.json`, `node_modules/`, and lockfile. This prevents global packages from interfering with each other through peer dependency conflicts, hoisting changes, or version resolution shifts.
|
|
124
|
+
|
|
125
|
+
Key changes:
|
|
126
|
+
|
|
127
|
+
- `pnpm add -g <pkg>` creates an isolated installation in `{pnpmHomeDir}/global/v11/{hash}/`
|
|
128
|
+
- `pnpm remove -g <pkg>` removes the entire installation group containing the package
|
|
129
|
+
- `pnpm update -g [pkg]` re-installs packages in new isolated directories
|
|
130
|
+
- `pnpm list -g` scans isolated directories to show all installed global packages
|
|
131
|
+
- `pnpm install -g` (no args) is no longer supported; use `pnpm add -g <pkg>` instead
|
|
132
|
+
|
|
133
|
+
### Patch Changes
|
|
134
|
+
|
|
135
|
+
- Updated dependencies [449dacf]
|
|
136
|
+
- Updated dependencies [76718b3]
|
|
137
|
+
- Updated dependencies [a8f016c]
|
|
138
|
+
- Updated dependencies [cc1b8e3]
|
|
139
|
+
- Updated dependencies [491a84f]
|
|
140
|
+
- Updated dependencies [13855ac]
|
|
141
|
+
- Updated dependencies [d7b8be4]
|
|
142
|
+
- Updated dependencies [7d2fd48]
|
|
143
|
+
- Updated dependencies [efb48dc]
|
|
144
|
+
- Updated dependencies [cb367b9]
|
|
145
|
+
- Updated dependencies [7b1c189]
|
|
146
|
+
- Updated dependencies [8ffb1a7]
|
|
147
|
+
- Updated dependencies [05fb1ae]
|
|
148
|
+
- Updated dependencies [71de2b3]
|
|
149
|
+
- Updated dependencies [10bc391]
|
|
150
|
+
- Updated dependencies [2df8b71]
|
|
151
|
+
- Updated dependencies [15549a9]
|
|
152
|
+
- Updated dependencies [cc7c0d2]
|
|
153
|
+
- Updated dependencies [efb48dc]
|
|
154
|
+
- @pnpm/bins.resolver@1001.0.0
|
|
155
|
+
- @pnpm/types@1001.0.0
|
|
156
|
+
- @pnpm/pkg-manifest.reader@1001.0.0
|
|
157
|
+
- @pnpm/crypto.hash@1001.0.0
|
package/lib/globalPackageDir.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
1
2
|
import fs from 'node:fs';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import util from 'node:util';
|
|
@@ -20,9 +21,24 @@ export function resolveInstallDir(globalDir, hash) {
|
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
23
|
export function createInstallDir(globalDir) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
// Ensure the parent exists, then create the per-group dir *exclusively*
|
|
25
|
+
// (no `recursive`, which would silently reuse an existing entry or follow
|
|
26
|
+
// a pre-existing symlink). The name adds random bytes on top of pid+time
|
|
27
|
+
// so it isn't predictable and can't collide within the same millisecond.
|
|
28
|
+
fs.mkdirSync(globalDir, { recursive: true });
|
|
29
|
+
for (let i = 0; i < 10; i++) {
|
|
30
|
+
const name = `${process.pid.toString(16)}-${Date.now().toString(16)}-${crypto.randomBytes(8).toString('hex')}`;
|
|
31
|
+
const dir = path.join(globalDir, name);
|
|
32
|
+
try {
|
|
33
|
+
fs.mkdirSync(dir);
|
|
34
|
+
return dir;
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
if (util.types.isNativeError(err) && 'code' in err && err.code === 'EEXIST')
|
|
38
|
+
continue;
|
|
39
|
+
throw err;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
throw new Error('Could not create a unique global install directory');
|
|
27
43
|
}
|
|
28
44
|
//# sourceMappingURL=globalPackageDir.js.map
|
package/lib/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { createGlobalCacheKey } from './cacheKey.js';
|
|
2
2
|
export { createInstallDir, getHashLink, resolveInstallDir, } from './globalPackageDir.js';
|
|
3
|
-
export { cleanOrphanedInstallDirs, findGlobalPackage, getGlobalPackageDetails, getInstalledBinNames, type GlobalPackageInfo, type InstalledGlobalPackage, scanGlobalPackages, } from './scanGlobalPackages.js';
|
|
3
|
+
export { cleanOrphanedInstallDirs, findGlobalPackage, getGlobalPackageDetails, getInstalledBinNames, type GlobalPackageInfo, type InstalledGlobalPackage, isValidGlobalDependencyAlias, scanGlobalPackages, } from './scanGlobalPackages.js';
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { createGlobalCacheKey } from './cacheKey.js';
|
|
2
2
|
export { createInstallDir, getHashLink, resolveInstallDir, } from './globalPackageDir.js';
|
|
3
|
-
export { cleanOrphanedInstallDirs, findGlobalPackage, getGlobalPackageDetails, getInstalledBinNames, scanGlobalPackages, } from './scanGlobalPackages.js';
|
|
3
|
+
export { cleanOrphanedInstallDirs, findGlobalPackage, getGlobalPackageDetails, getInstalledBinNames, isValidGlobalDependencyAlias, scanGlobalPackages, } from './scanGlobalPackages.js';
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
|
@@ -3,6 +3,43 @@ import path from 'node:path';
|
|
|
3
3
|
import util from 'node:util';
|
|
4
4
|
import { getBinsFromPackageManifest } from '@pnpm/bins.resolver';
|
|
5
5
|
import { readPackageJsonFromDirRawSync, safeReadPackageJsonFromDir } from '@pnpm/pkg-manifest.reader';
|
|
6
|
+
const RESERVED_ALIASES = new Set(['node_modules', 'favicon.ico']);
|
|
7
|
+
const isUrlFriendly = (segment) => encodeURIComponent(segment) === segment;
|
|
8
|
+
// A dependency alias from a global group's package.json becomes a directory
|
|
9
|
+
// name under `node_modules` at every join site (list, conflict-check,
|
|
10
|
+
// remove, update). A tampered manifest could use an alias like `../x` or an
|
|
11
|
+
// absolute path to escape the install dir, so only valid npm package names
|
|
12
|
+
// are trusted. This applies the same `validForOldPackages` rules that
|
|
13
|
+
// `validate-npm-package-name` (and `@pnpm/fs.symlink-dependency`'s
|
|
14
|
+
// `safeJoinModulesDir`) enforce — implemented inline to avoid adding a
|
|
15
|
+
// dependency to this low-level package.
|
|
16
|
+
export function isValidGlobalDependencyAlias(alias) {
|
|
17
|
+
if (alias.length === 0)
|
|
18
|
+
return false;
|
|
19
|
+
if (/^[._-]/.test(alias))
|
|
20
|
+
return false;
|
|
21
|
+
if (alias.trim() !== alias)
|
|
22
|
+
return false;
|
|
23
|
+
if (RESERVED_ALIASES.has(alias.toLowerCase()))
|
|
24
|
+
return false;
|
|
25
|
+
if (isUrlFriendly(alias))
|
|
26
|
+
return true;
|
|
27
|
+
const scoped = /^@([^/]+)\/([^/]+)$/.exec(alias);
|
|
28
|
+
if (scoped) {
|
|
29
|
+
const [, scope, name] = scoped;
|
|
30
|
+
return !name.startsWith('.') && isUrlFriendly(scope) && isUrlFriendly(name);
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
function pickValidDependencies(dependencies) {
|
|
35
|
+
const result = {};
|
|
36
|
+
for (const [alias, spec] of Object.entries(dependencies)) {
|
|
37
|
+
if (isValidGlobalDependencyAlias(alias)) {
|
|
38
|
+
result[alias] = spec;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
6
43
|
export function scanGlobalPackages(globalDir) {
|
|
7
44
|
let entries;
|
|
8
45
|
try {
|
|
@@ -34,12 +71,15 @@ export function scanGlobalPackages(globalDir) {
|
|
|
34
71
|
catch {
|
|
35
72
|
continue;
|
|
36
73
|
}
|
|
37
|
-
if (!pkgJson.dependencies
|
|
74
|
+
if (!pkgJson.dependencies)
|
|
75
|
+
continue;
|
|
76
|
+
const dependencies = pickValidDependencies(pkgJson.dependencies);
|
|
77
|
+
if (Object.keys(dependencies).length === 0)
|
|
38
78
|
continue;
|
|
39
79
|
result.push({
|
|
40
80
|
hash: entry.name,
|
|
41
81
|
installDir,
|
|
42
|
-
dependencies
|
|
82
|
+
dependencies,
|
|
43
83
|
});
|
|
44
84
|
}
|
|
45
85
|
return result;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/global.packages",
|
|
3
|
-
"version": "1100.0.
|
|
3
|
+
"version": "1100.0.11",
|
|
4
4
|
"description": "Utilities for managing isolated global packages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -28,14 +28,14 @@
|
|
|
28
28
|
"!*.map"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@pnpm/
|
|
32
|
-
"@pnpm/
|
|
33
|
-
"@pnpm/
|
|
34
|
-
"@pnpm/
|
|
35
|
-
"@pnpm/
|
|
31
|
+
"@pnpm/bins.resolver": "1100.0.9",
|
|
32
|
+
"@pnpm/crypto.hash": "1100.0.1",
|
|
33
|
+
"@pnpm/pkg-manifest.reader": "1100.0.10",
|
|
34
|
+
"@pnpm/types": "1101.4.0",
|
|
35
|
+
"@pnpm/util.lex-comparator": "^4.0.1"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@pnpm/global.packages": "1100.0.
|
|
38
|
+
"@pnpm/global.packages": "1100.0.11"
|
|
39
39
|
},
|
|
40
40
|
"engines": {
|
|
41
41
|
"node": ">=22.13"
|