@pnpm/exe 12.2.0 → 12.3.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/bin/pnpm.mjs +6 -3
- package/dist/node_modules/.pnpm-workspace-state-v1.json +3 -3
- package/install.js +54 -14
- package/native-binary.mjs +32 -6
- package/package.json +12 -11
- package/pnpm +21 -0
- package/pnpm.exe +0 -4
package/bin/pnpm.mjs
CHANGED
|
@@ -3,14 +3,17 @@
|
|
|
3
3
|
// `./bin/pnpx.mjs` for every pnpm >=11 (see its `config.json`) and loads them
|
|
4
4
|
// into its own Node.js process, which a native executable cannot be loaded into.
|
|
5
5
|
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
6
|
+
// The `pnpm` placeholder bin runs it too, when the install script that
|
|
7
|
+
// replaces it with the native binary did not run (build scripts blocked). An
|
|
8
|
+
// ordinary `npm install -g pnpm` never pays for a Node.js startup:
|
|
9
|
+
// `package.json#bin` points at the native binary.
|
|
8
10
|
//
|
|
9
11
|
// Corepack installs no dependencies and runs no lifecycle scripts, so the
|
|
10
12
|
// `@pnpm/exe.<target>` package that carries the binary is absent and
|
|
11
13
|
// `install.js` never ran. The binary is therefore downloaded on first use and
|
|
12
14
|
// kept next to this wrapper — where the native binary also finds the `dist/`
|
|
13
|
-
// payload it ships node-gyp in.
|
|
15
|
+
// payload it ships node-gyp in. The placeholder's installs usually do carry
|
|
16
|
+
// that package, and the binary is taken from there.
|
|
14
17
|
//
|
|
15
18
|
// The download itself is `get-pnpm`, the package behind https://get.pnpm.io,
|
|
16
19
|
// which already knows how to verify one; it travels in that same `dist/`
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"lastValidatedTimestamp":
|
|
2
|
+
"lastValidatedTimestamp": 1788364975827,
|
|
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.3.0"
|
|
7
7
|
}
|
|
8
8
|
},
|
|
9
9
|
"pnpmfiles": [],
|
|
@@ -132,7 +132,7 @@
|
|
|
132
132
|
"escape-string-regexp": "^5.0.0",
|
|
133
133
|
"eslint": "^10.9.1",
|
|
134
134
|
"eslint-plugin-import-x": "^4.17.1",
|
|
135
|
-
"eslint-plugin-jest": "^29.16.
|
|
135
|
+
"eslint-plugin-jest": "^29.16.6",
|
|
136
136
|
"eslint-plugin-n": "^18.3.0",
|
|
137
137
|
"eslint-plugin-promise": "^7.3.0",
|
|
138
138
|
"eslint-plugin-regexp": "^3.1.1",
|
package/install.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Preinstall for the pnpm v12 wrapper (shared verbatim by `pnpm` and
|
|
3
|
-
// `@pnpm/exe`): replace the
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
3
|
+
// `@pnpm/exe`): replace the placeholder bins with the host's native binary so
|
|
4
|
+
// `pnpm` runs directly, no Node startup per call. Package managers write bin
|
|
5
|
+
// shims after preinstall, so the shims are made from the binary; where build
|
|
6
|
+
// scripts are blocked (`--ignore-scripts`, the pnpm/Bun default) the
|
|
7
|
+
// placeholder stays and runs pnpm through Node.js (see the `pnpm` file). npm
|
|
8
|
+
// does not re-read the rewritten `bin` during the same install pass, so on a
|
|
9
|
+
// global Windows install, postinstall asks it to relink.
|
|
9
10
|
//
|
|
10
11
|
// `pn`/`pnpx`/`pnx` are committed `#!/bin/sh` scripts on Unix (so only `pnpm` is
|
|
11
12
|
// relinked); on Windows the native binary is hardlinked onto each and
|
|
@@ -15,6 +16,7 @@
|
|
|
15
16
|
// Corepack runs no lifecycle scripts, so it never gets here; it enters through
|
|
16
17
|
// `bin/pnpm.mjs` instead.
|
|
17
18
|
import console from 'node:console'
|
|
19
|
+
import { spawnSync } from 'node:child_process'
|
|
18
20
|
import fs from 'node:fs'
|
|
19
21
|
import path from 'node:path'
|
|
20
22
|
import process from 'node:process'
|
|
@@ -28,7 +30,11 @@ import {
|
|
|
28
30
|
|
|
29
31
|
const BIN_NAMES = ['pnpm', 'pn', 'pnpx', 'pnx']
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
if (process.env.npm_lifecycle_event === 'postinstall') {
|
|
34
|
+
relinkNpmWindowsShims()
|
|
35
|
+
} else {
|
|
36
|
+
setup()
|
|
37
|
+
}
|
|
32
38
|
|
|
33
39
|
function setup () {
|
|
34
40
|
// The committed manifest has no `optionalDependencies`; generate-packages.mjs
|
|
@@ -64,7 +70,7 @@ function setup () {
|
|
|
64
70
|
}
|
|
65
71
|
rewriteBin(newBin)
|
|
66
72
|
} else {
|
|
67
|
-
placeBinary(nativeBinary, path.join(wrapperDir, 'pnpm
|
|
73
|
+
placeBinary(nativeBinary, path.join(wrapperDir, 'pnpm'), 0o755)
|
|
68
74
|
}
|
|
69
75
|
}
|
|
70
76
|
|
|
@@ -94,9 +100,7 @@ function placeBinary (nativeBinary, destPath, mode) {
|
|
|
94
100
|
}
|
|
95
101
|
fs.renameSync(tempPath, destPath)
|
|
96
102
|
} catch (err) {
|
|
97
|
-
|
|
98
|
-
fs.rmSync(tempPath, { force: true })
|
|
99
|
-
} catch {}
|
|
103
|
+
removeFileIfPossible(tempPath)
|
|
100
104
|
fail(`Could not install the pnpm binary at ${destPath}: ${err.message}`)
|
|
101
105
|
}
|
|
102
106
|
}
|
|
@@ -111,9 +115,45 @@ function rewriteBin (binMap) {
|
|
|
111
115
|
fs.writeFileSync(tempPath, JSON.stringify(pkg, null, 2))
|
|
112
116
|
fs.renameSync(tempPath, pkgJsonPath)
|
|
113
117
|
} catch {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
118
|
+
removeFileIfPossible(tempPath)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function relinkNpmWindowsShims () {
|
|
123
|
+
const npmExecPath = process.env.npm_execpath
|
|
124
|
+
if (
|
|
125
|
+
process.platform !== 'win32' ||
|
|
126
|
+
process.env.npm_config_global !== 'true' ||
|
|
127
|
+
npmExecPath == null ||
|
|
128
|
+
path.basename(npmExecPath).toLowerCase() !== 'npm-cli.js'
|
|
129
|
+
) {
|
|
130
|
+
return
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const packageName = readWrapperManifest().name
|
|
134
|
+
if (typeof packageName !== 'string') {
|
|
135
|
+
fail('Could not determine the pnpm wrapper package name when regenerating npm shims.')
|
|
136
|
+
}
|
|
137
|
+
const result = spawnSync(process.execPath, [
|
|
138
|
+
npmExecPath,
|
|
139
|
+
'rebuild',
|
|
140
|
+
'--global',
|
|
141
|
+
'--ignore-scripts',
|
|
142
|
+
packageName,
|
|
143
|
+
], { stdio: 'inherit' })
|
|
144
|
+
if (result.error != null) {
|
|
145
|
+
fail(`Could not regenerate the npm shims for pnpm: ${result.error.message}`)
|
|
146
|
+
}
|
|
147
|
+
if (result.status !== 0) {
|
|
148
|
+
fail('npm could not regenerate the shims for pnpm.')
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function removeFileIfPossible (filePath) {
|
|
153
|
+
try {
|
|
154
|
+
fs.rmSync(filePath, { force: true })
|
|
155
|
+
} catch {
|
|
156
|
+
return
|
|
117
157
|
}
|
|
118
158
|
}
|
|
119
159
|
|
package/native-binary.mjs
CHANGED
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
// (`install.js`), which links it over the placeholder bins, and by the Corepack
|
|
3
3
|
// entry (`bin/pnpm.mjs`), which spawns it.
|
|
4
4
|
import fs from 'node:fs'
|
|
5
|
-
import { createRequire } from 'node:module'
|
|
6
5
|
import path from 'node:path'
|
|
7
6
|
import process from 'node:process'
|
|
8
7
|
import { fileURLToPath } from 'node:url'
|
|
9
8
|
|
|
10
|
-
const require = createRequire(import.meta.url)
|
|
11
9
|
const { platform, arch } = process
|
|
12
10
|
|
|
13
11
|
/** Directory of the published wrapper; the native binary lives next to it. */
|
|
@@ -69,7 +67,14 @@ export function splitBinSpecifier (specifier) {
|
|
|
69
67
|
|
|
70
68
|
/**
|
|
71
69
|
* Path to the native binary of whichever platform package the package manager
|
|
72
|
-
* installed, or `null` when none is present (Corepack,
|
|
70
|
+
* installed with this wrapper, or `null` when none is present (Corepack,
|
|
71
|
+
* `--no-optional`).
|
|
72
|
+
*
|
|
73
|
+
* Only the wrapper's own `node_modules` and the one it was installed into are
|
|
74
|
+
* searched, which is where every package manager puts an optional dependency
|
|
75
|
+
* of the wrapper. A `require` walk would also reach the ancestors' `node_modules`,
|
|
76
|
+
* which belong to whatever project the wrapper sits under and are not to be
|
|
77
|
+
* run in its name.
|
|
73
78
|
*
|
|
74
79
|
* @returns {string | null}
|
|
75
80
|
*/
|
|
@@ -77,13 +82,34 @@ export function resolveInstalledBinary () {
|
|
|
77
82
|
// Use whichever platform package the package manager installed: it already
|
|
78
83
|
// filtered by `os`/`cpu`/`libc`, more reliable than re-deriving the host.
|
|
79
84
|
for (const specifier of getBinCandidates()) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
85
|
+
const { packageName, binFile } = splitBinSpecifier(specifier)
|
|
86
|
+
for (const modulesDir of installedModulesDirs()) {
|
|
87
|
+
const candidate = path.join(modulesDir, ...packageName.split('/'), binFile)
|
|
88
|
+
if (fs.statSync(candidate, { throwIfNoEntry: false })?.isFile() === true) {
|
|
89
|
+
return candidate
|
|
90
|
+
}
|
|
91
|
+
}
|
|
83
92
|
}
|
|
84
93
|
return null
|
|
85
94
|
}
|
|
86
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Where a platform package installed for this wrapper can be: the `node_modules`
|
|
98
|
+
* nested in the wrapper, then the one the wrapper was installed into (two levels
|
|
99
|
+
* up for the scoped `@pnpm/exe`). Neither need exist. Throws only when the
|
|
100
|
+
* wrapper's manifest is unreadable, see {@link readWrapperManifest}.
|
|
101
|
+
*
|
|
102
|
+
* @returns {string[]}
|
|
103
|
+
*/
|
|
104
|
+
function installedModulesDirs () {
|
|
105
|
+
const { name } = readWrapperManifest()
|
|
106
|
+
const segments = typeof name === 'string' ? name.split('/').length : 1
|
|
107
|
+
return [
|
|
108
|
+
path.join(wrapperDir, 'node_modules'),
|
|
109
|
+
path.resolve(wrapperDir, ...Array(segments).fill('..')),
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
|
|
87
113
|
// A successful read with no optionalDependencies is the dev checkout (there is
|
|
88
114
|
// no native binary to link there); a read/parse failure is a corrupt published
|
|
89
115
|
// package and must not be silently swallowed into that same path.
|
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.3.0",
|
|
13
13
|
"description": "Fast, disk space efficient package manager",
|
|
14
14
|
"keywords": [
|
|
15
15
|
"pnpm",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"directory": "pnpm/npm/pnpm-exe"
|
|
26
26
|
},
|
|
27
27
|
"bin": {
|
|
28
|
-
"pnpm": "pnpm
|
|
28
|
+
"pnpm": "pnpm",
|
|
29
29
|
"pn": "pn",
|
|
30
30
|
"pnpx": "pnpx",
|
|
31
31
|
"pnx": "pnx"
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"node": ">=18.*"
|
|
36
36
|
},
|
|
37
37
|
"files": [
|
|
38
|
-
"pnpm
|
|
38
|
+
"pnpm",
|
|
39
39
|
"pn",
|
|
40
40
|
"pnpx",
|
|
41
41
|
"pnx",
|
|
@@ -46,17 +46,18 @@
|
|
|
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-x64-musl": "12.
|
|
56
|
-
"@pnpm/exe.linux-arm64-musl": "12.
|
|
49
|
+
"@pnpm/exe.win32-x64": "12.3.0",
|
|
50
|
+
"@pnpm/exe.win32-arm64": "12.3.0",
|
|
51
|
+
"@pnpm/exe.darwin-x64": "12.3.0",
|
|
52
|
+
"@pnpm/exe.darwin-arm64": "12.3.0",
|
|
53
|
+
"@pnpm/exe.linux-x64": "12.3.0",
|
|
54
|
+
"@pnpm/exe.linux-arm64": "12.3.0",
|
|
55
|
+
"@pnpm/exe.linux-x64-musl": "12.3.0",
|
|
56
|
+
"@pnpm/exe.linux-arm64-musl": "12.3.0"
|
|
57
57
|
},
|
|
58
58
|
"scripts": {
|
|
59
59
|
"preinstall": "node install.js",
|
|
60
|
+
"postinstall": "node install.js",
|
|
60
61
|
"bundle-node-gyp": "node scripts/bundle-node-gyp.mjs"
|
|
61
62
|
}
|
|
62
63
|
}
|
package/pnpm
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// pnpm's native binary replaces this file during installation (see
|
|
3
|
+
// ./install.js). If this is running, that install script did not — build
|
|
4
|
+
// scripts were blocked (pnpm and Bun block them by default) or skipped
|
|
5
|
+
// (`--ignore-scripts`) — so pnpm runs through Node.js instead: `bin/pnpm.mjs`
|
|
6
|
+
// finds the installed binary, or downloads one, and spawns it.
|
|
7
|
+
//
|
|
8
|
+
// Package managers write bin shims after preinstall has had its chance to run,
|
|
9
|
+
// so a shim made from this file's shebang exists only where the binary never
|
|
10
|
+
// arrived. That is also why this file is left in place once it is running: a
|
|
11
|
+
// binary put here under such a shim would be run through `node`.
|
|
12
|
+
import process from 'node:process'
|
|
13
|
+
|
|
14
|
+
if (process.stderr.isTTY) {
|
|
15
|
+
process.stderr.write(
|
|
16
|
+
'pnpm is running through Node.js because the script that installs its native binary was skipped. ' +
|
|
17
|
+
'Reinstall pnpm with its build scripts allowed to run the binary directly.\n'
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
await import('./bin/pnpm.mjs')
|
package/pnpm.exe
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
This is a placeholder. pnpm's native binary replaces this file during
|
|
2
|
-
installation (see ./install.js). If you are reading this, the install/build
|
|
3
|
-
script did not run — reinstall with build scripts enabled (e.g. allow-list
|
|
4
|
-
pnpm's build under pnpm or Bun, or drop --ignore-scripts).
|