@pnpm/exe 12.0.0-rc.0 → 12.0.0-rc.10

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.
Files changed (31) hide show
  1. package/README.md +12 -0
  2. package/THIRD-PARTY-NOTICES.md +42 -0
  3. package/bin/pnpm.mjs +141 -0
  4. package/bin/pnpx.mjs +9 -0
  5. package/dist/node_modules/.bin/get-pnpm +50 -0
  6. package/dist/node_modules/.bin/node-gyp +13 -1
  7. package/dist/node_modules/.bin/node-which +13 -1
  8. package/dist/node_modules/.bin/nopt +13 -1
  9. package/dist/node_modules/.bin/semver +13 -1
  10. package/dist/node_modules/.package-map.json +1 -1
  11. package/dist/node_modules/.pnpm-workspace-state-v1.json +70 -21
  12. package/dist/node_modules/get-pnpm/bin/get-pnpm.js +11 -0
  13. package/dist/node_modules/get-pnpm/lib/downloadExecutable.js +99 -0
  14. package/dist/node_modules/get-pnpm/lib/extractTarball.js +23 -0
  15. package/dist/node_modules/get-pnpm/lib/extractTarballMember.js +128 -0
  16. package/dist/node_modules/get-pnpm/lib/index.js +208 -0
  17. package/dist/node_modules/get-pnpm/lib/npmSigningKeys.js +23 -0
  18. package/dist/node_modules/get-pnpm/lib/platformPackageName.js +60 -0
  19. package/dist/node_modules/get-pnpm/lib/registry.js +120 -0
  20. package/dist/node_modules/get-pnpm/lib/resolveVersion.js +36 -0
  21. package/dist/node_modules/get-pnpm/lib/sameFileContents.js +45 -0
  22. package/dist/node_modules/get-pnpm/lib/verifySignature.js +51 -0
  23. package/dist/node_modules/get-pnpm/package.json +45 -0
  24. package/dist/node_modules/node-gyp/.release-please-manifest.json +1 -1
  25. package/dist/node_modules/node-gyp/gyp/.release-please-manifest.json +1 -1
  26. package/dist/node_modules/node-gyp/gyp/pyproject.toml +4 -4
  27. package/dist/node_modules/node-gyp/lib/download.js +3 -3
  28. package/dist/node_modules/node-gyp/package.json +1 -1
  29. package/install.js +20 -97
  30. package/native-binary.mjs +116 -0
  31. package/package.json +13 -10
@@ -0,0 +1,51 @@
1
+ import { createVerify } from 'node:crypto';
2
+ import { NPM_SIGNING_KEYS } from './npmSigningKeys.js';
3
+ /**
4
+ * Checks the registry's signature over a package's identity and checksum.
5
+ *
6
+ * The registry serves both the tarball and the checksum, so a checksum taken
7
+ * from it proves nothing on its own. This is what makes it worth anything: the
8
+ * signature is made with a key the registry publishes but the download host
9
+ * cannot mint, and the trusted copy of that key ships inside this package.
10
+ *
11
+ * @throws if the package is unsigned, signed with a key that isn't trusted or
12
+ * has expired, or the signature does not verify.
13
+ */
14
+ export function verifyRegistrySignature(opts) {
15
+ const pkg = `${opts.name}@${opts.version}`;
16
+ const signatures = opts.signatures ?? [];
17
+ if (signatures.length === 0) {
18
+ throw new Error(`${pkg} carries no npm registry signature, so it cannot be verified.`);
19
+ }
20
+ // Pick the signature by key rather than by position. A package can carry
21
+ // several, in no guaranteed order, and across a rotation one of them can be
22
+ // from a key this installer does not pin — which is not a reason to refuse a
23
+ // package that another, pinned key also signed.
24
+ const keys = opts.keys ?? NPM_SIGNING_KEYS;
25
+ const match = signatures
26
+ .map((signature) => ({ signature, key: keys.find(({ keyid }) => keyid === signature.keyid) }))
27
+ .find((candidate) => candidate.key != null);
28
+ if (match?.key == null) {
29
+ throw new Error(`${pkg} is signed with an unexpected npm key (${signatures.map(({ keyid }) => keyid).join(', ')}).
30
+
31
+ If npm has rotated its signing key, this installer needs updating.
32
+ Until then, install pnpm another way: https://pnpm.io/installation`);
33
+ }
34
+ const { signature, key } = match;
35
+ if (key.expires != null) {
36
+ const expires = new Date(key.expires).getTime();
37
+ // An unreadable date must not read as "never expires".
38
+ if (Number.isNaN(expires)) {
39
+ throw new Error(`${pkg} is signed with an npm key whose expiry date cannot be read (${key.expires}).`);
40
+ }
41
+ if (expires < (opts.now ?? new Date()).getTime()) {
42
+ throw new Error(`${pkg} is signed with an npm key that expired on ${key.expires}.`);
43
+ }
44
+ }
45
+ // Registry signatures cover the package identity and its content hash.
46
+ const message = `${pkg}:${opts.integrity}`;
47
+ const publicKey = `-----BEGIN PUBLIC KEY-----\n${key.key}\n-----END PUBLIC KEY-----`;
48
+ if (!createVerify('SHA256').update(message).verify(publicKey, signature.sig, 'base64')) {
49
+ throw new Error(`The npm registry signature for ${pkg} is not valid. Refusing to install.`);
50
+ }
51
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "get-pnpm",
3
+ "version": "0.0.3",
4
+ "description": "Installs pnpm as a standalone executable",
5
+ "keywords": [
6
+ "pnpm",
7
+ "install",
8
+ "installer"
9
+ ],
10
+ "license": "MIT",
11
+ "funding": "https://opencollective.com/pnpm",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/pnpm/get.pnpm.io/tree/main/get-pnpm"
15
+ },
16
+ "homepage": "https://github.com/pnpm/get.pnpm.io/tree/main/get-pnpm#readme",
17
+ "bugs": {
18
+ "url": "https://github.com/pnpm/get.pnpm.io/issues"
19
+ },
20
+ "type": "module",
21
+ "main": "lib/index.js",
22
+ "types": "lib/index.d.ts",
23
+ "exports": {
24
+ ".": "./lib/index.js"
25
+ },
26
+ "files": [
27
+ "lib",
28
+ "!*.map",
29
+ "bin"
30
+ ],
31
+ "bin": {
32
+ "get-pnpm": "bin/get-pnpm.js"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^24.10.1",
36
+ "typescript": "^5.9.3"
37
+ },
38
+ "engines": {
39
+ "node": ">=22.13"
40
+ },
41
+ "scripts": {
42
+ "build": "tsc",
43
+ "test": "tsc && node --test test/*.test.ts"
44
+ }
45
+ }
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "12.4.0"
2
+ ".": "12.3.0"
3
3
  }
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "0.22.2"
2
+ ".": "0.22.1"
3
3
  }
@@ -4,20 +4,20 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "gyp-next"
7
- version = "0.22.2"
7
+ version = "0.22.1"
8
8
  authors = [
9
9
  { name="Node.js contributors", email="ryzokuken@disroot.org" },
10
10
  ]
11
11
  description = "A fork of the GYP build system for use in the Node.js projects"
12
12
  readme = "README.md"
13
- license = "BSD-3-Clause"
14
- license-files = ["LICENSE"]
13
+ license = { file="LICENSE" }
15
14
  requires-python = ">=3.9"
16
- dependencies = ["packaging>=24.0", "setuptools>=77.0.3"]
15
+ dependencies = ["packaging>=24.0", "setuptools>=69.5.1"]
17
16
  classifiers = [
18
17
  "Development Status :: 3 - Alpha",
19
18
  "Environment :: Console",
20
19
  "Intended Audience :: Developers",
20
+ "License :: OSI Approved :: BSD License",
21
21
  "Natural Language :: English",
22
22
  "Programming Language :: Python",
23
23
  "Programming Language :: Python :: 3",
@@ -1,5 +1,5 @@
1
1
  const { Readable } = require('stream')
2
- const { Agent, EnvHttpProxyAgent, RetryAgent, fetch } = require('undici')
2
+ const { EnvHttpProxyAgent } = require('undici')
3
3
  const { promises: fs } = require('graceful-fs')
4
4
  const log = require('./log')
5
5
 
@@ -48,7 +48,7 @@ async function createDispatcher (gyp) {
48
48
  const env = process.env
49
49
  const hasProxyEnv = env.http_proxy || env.HTTP_PROXY || env.https_proxy || env.HTTPS_PROXY
50
50
  if (!gyp.opts.proxy && !gyp.opts.cafile && !hasProxyEnv) {
51
- return new RetryAgent(new Agent(), { maxRetries: 3 })
51
+ return undefined
52
52
  }
53
53
 
54
54
  const opts = {}
@@ -69,7 +69,7 @@ async function createDispatcher (gyp) {
69
69
  if (gyp.opts.noproxy) {
70
70
  opts.noProxy = gyp.opts.noproxy
71
71
  }
72
- return new RetryAgent(new EnvHttpProxyAgent(opts), { maxRetries: 3 })
72
+ return new EnvHttpProxyAgent(opts)
73
73
  }
74
74
 
75
75
  async function readCAFile (filename) {
@@ -11,7 +11,7 @@
11
11
  "bindings",
12
12
  "gyp"
13
13
  ],
14
- "version": "12.4.0",
14
+ "version": "12.3.0",
15
15
  "installVersion": 11,
16
16
  "author": "Nathan Rajlich <nathan@tootallnate.net> (http://tootallnate.net)",
17
17
  "repository": {
package/install.js CHANGED
@@ -10,37 +10,20 @@
10
10
  // relinked); on Windows the native binary is hardlinked onto each and
11
11
  // self-detects its launch name to inject `dlx` (see `argv_with_alias_subcommand`
12
12
  // in the cli crate).
13
+ //
14
+ // Corepack runs no lifecycle scripts, so it never gets here; it enters through
15
+ // `bin/pnpm.mjs` instead.
13
16
  import console from 'node:console'
14
17
  import fs from 'node:fs'
15
- import { createRequire } from 'node:module'
16
18
  import path from 'node:path'
17
19
  import process from 'node:process'
18
- import { fileURLToPath } from 'node:url'
19
-
20
- const require = createRequire(import.meta.url)
21
- const ownDir = path.dirname(fileURLToPath(import.meta.url))
22
- const { platform, arch } = process
23
-
24
- const PLATFORMS = {
25
- win32: {
26
- x64: '@pnpm/exe.win32-x64/pnpm.exe',
27
- arm64: '@pnpm/exe.win32-arm64/pnpm.exe',
28
- },
29
- darwin: {
30
- x64: '@pnpm/exe.darwin-x64/pnpm',
31
- arm64: '@pnpm/exe.darwin-arm64/pnpm',
32
- },
33
- linux: {
34
- x64: {
35
- glibc: '@pnpm/exe.linux-x64/pnpm',
36
- musl: '@pnpm/exe.linux-x64-musl/pnpm',
37
- },
38
- arm64: {
39
- glibc: '@pnpm/exe.linux-arm64/pnpm',
40
- musl: '@pnpm/exe.linux-arm64-musl/pnpm',
41
- },
42
- },
43
- }
20
+ import {
21
+ getBinCandidates,
22
+ readWrapperManifest,
23
+ resolveInstalledBinary,
24
+ splitBinSpecifier,
25
+ wrapperDir,
26
+ } from './native-binary.mjs'
44
27
 
45
28
  const BIN_NAMES = ['pnpm', 'pn', 'pnpx', 'pnx']
46
29
 
@@ -50,45 +33,37 @@ function setup () {
50
33
  // The committed manifest has no `optionalDependencies`; generate-packages.mjs
51
34
  // adds them at release time. Without them this is the monorepo checkout, where
52
35
  // the wrapper is a workspace package and there is no native binary to link.
53
- if (readOwnManifest().optionalDependencies == null) {
36
+ if (readWrapperManifest().optionalDependencies == null) {
54
37
  return
55
38
  }
56
39
 
57
40
  const candidates = getBinCandidates()
58
41
  if (candidates.length === 0) {
59
- fail(`pnpm does not ship a prebuilt binary for ${platform}-${arch}.`)
42
+ fail(`pnpm does not ship a prebuilt binary for ${process.platform}-${process.arch}.`)
60
43
  }
61
44
 
62
- // Use whichever platform package the package manager installed: it already
63
- // filtered by `os`/`cpu`/`libc`, more reliable than re-deriving the host.
64
- let nativeBinary
65
- for (const target of candidates) {
66
- try {
67
- nativeBinary = require.resolve(target)
68
- break
69
- } catch {}
70
- }
45
+ const nativeBinary = resolveInstalledBinary()
71
46
  if (nativeBinary == null) {
72
- const pkgName = candidates[0].split('/').slice(0, 2).join('/')
47
+ const { packageName } = splitBinSpecifier(candidates[0])
73
48
  fail(
74
- `The "${pkgName}" package is not installed, so pnpm has no native binary to run.\n` +
49
+ `The "${packageName}" package is not installed, so pnpm has no native binary to run.\n` +
75
50
  'If your package manager skipped optional dependencies or blocked build scripts, ' +
76
51
  'enable them and reinstall.'
77
52
  )
78
53
  }
79
54
 
80
- if (platform === 'win32') {
55
+ if (process.platform === 'win32') {
81
56
  const newBin = {}
82
57
  for (const name of BIN_NAMES) {
83
58
  // The existing shim points at the no-ext file, so it must become the
84
59
  // binary; the `.exe` twin + bin rewrite are for shims generated later.
85
- placeBinary(nativeBinary, path.join(ownDir, `${name}.exe`))
86
- placeBinary(nativeBinary, path.join(ownDir, name))
60
+ placeBinary(nativeBinary, path.join(wrapperDir, `${name}.exe`))
61
+ placeBinary(nativeBinary, path.join(wrapperDir, name))
87
62
  newBin[name] = `${name}.exe`
88
63
  }
89
64
  rewriteBin(newBin)
90
65
  } else {
91
- placeBinary(nativeBinary, path.join(ownDir, 'pnpm'), 0o755)
66
+ placeBinary(nativeBinary, path.join(wrapperDir, 'pnpm'), 0o755)
92
67
  }
93
68
  }
94
69
 
@@ -126,7 +101,7 @@ function placeBinary (nativeBinary, destPath, mode) {
126
101
  }
127
102
 
128
103
  function rewriteBin (binMap) {
129
- const pkgJsonPath = path.join(ownDir, 'package.json')
104
+ const pkgJsonPath = path.join(wrapperDir, 'package.json')
130
105
  // Temp file + rename, not in-place: package.json is hard-linked from the store.
131
106
  const tempPath = `${pkgJsonPath}.pnpm-tmp`
132
107
  try {
@@ -145,55 +120,3 @@ function fail (message) {
145
120
  console.error(message)
146
121
  process.exit(1)
147
122
  }
148
-
149
- // A successful read with no optionalDependencies is the dev checkout (setup
150
- // no-ops there); a read/parse failure is a corrupt published package and must
151
- // not be silently swallowed into that same no-op path.
152
- function readOwnManifest () {
153
- const manifestPath = path.join(ownDir, 'package.json')
154
- let manifest
155
- try {
156
- manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'))
157
- } catch (err) {
158
- throw new Error(`Failed to read ${manifestPath}: ${err.message}`)
159
- }
160
- if (typeof manifest !== 'object' || manifest == null || Array.isArray(manifest)) {
161
- throw new Error(`Expected ${manifestPath} to contain a JSON object`)
162
- }
163
- return manifest
164
- }
165
-
166
- /**
167
- * Native binary specifiers to try, most-preferred first; empty when the host is
168
- * unsupported. The linux glibc/musl pair is ordered by detected libc, which
169
- * only decides the winner when both are installed (e.g. `npm install --force`).
170
- *
171
- * @returns {string[]}
172
- */
173
- function getBinCandidates () {
174
- const platformEntry = PLATFORMS?.[platform]?.[arch]
175
-
176
- if (platformEntry == null) {
177
- return []
178
- }
179
- if (typeof platformEntry === 'string') {
180
- return [platformEntry]
181
- }
182
-
183
- const order = detectLinuxLibc() === 'musl' ? ['musl', 'glibc'] : ['glibc', 'musl']
184
- return order.map((libc) => platformEntry[libc])
185
- }
186
-
187
- function detectLinuxLibc () {
188
- if (platform !== 'linux') {
189
- return null
190
- }
191
-
192
- // glibc builds set `glibcVersionRuntime`; musl leaves it unset. Guarded —
193
- // `process.report` may be unavailable, leaving ordering to the default.
194
- try {
195
- return process.report?.getReport().header.glibcVersionRuntime ? 'glibc' : 'musl'
196
- } catch {
197
- return null
198
- }
199
- }
@@ -0,0 +1,116 @@
1
+ // Where the host's native pnpm binary comes from. Shared by the preinstall
2
+ // (`install.js`), which links it over the placeholder bins, and by the Corepack
3
+ // entry (`bin/pnpm.mjs`), which spawns it.
4
+ import fs from 'node:fs'
5
+ import { createRequire } from 'node:module'
6
+ import path from 'node:path'
7
+ import process from 'node:process'
8
+ import { fileURLToPath } from 'node:url'
9
+
10
+ const require = createRequire(import.meta.url)
11
+ const { platform, arch } = process
12
+
13
+ /** Directory of the published wrapper; the native binary lives next to it. */
14
+ export const wrapperDir = path.dirname(fileURLToPath(import.meta.url))
15
+
16
+ const PLATFORMS = {
17
+ win32: {
18
+ x64: '@pnpm/exe.win32-x64/pnpm.exe',
19
+ arm64: '@pnpm/exe.win32-arm64/pnpm.exe',
20
+ },
21
+ darwin: {
22
+ x64: '@pnpm/exe.darwin-x64/pnpm',
23
+ arm64: '@pnpm/exe.darwin-arm64/pnpm',
24
+ },
25
+ linux: {
26
+ x64: {
27
+ glibc: '@pnpm/exe.linux-x64/pnpm',
28
+ musl: '@pnpm/exe.linux-x64-musl/pnpm',
29
+ },
30
+ arm64: {
31
+ glibc: '@pnpm/exe.linux-arm64/pnpm',
32
+ musl: '@pnpm/exe.linux-arm64-musl/pnpm',
33
+ },
34
+ },
35
+ }
36
+
37
+ /**
38
+ * Native binary specifiers to try, most-preferred first; empty when the host is
39
+ * unsupported. The linux glibc/musl pair is ordered by detected libc, which
40
+ * only decides the winner when both are installed (e.g. `npm install --force`).
41
+ *
42
+ * @returns {string[]}
43
+ */
44
+ export function getBinCandidates () {
45
+ const platformEntry = PLATFORMS?.[platform]?.[arch]
46
+
47
+ if (platformEntry == null) {
48
+ return []
49
+ }
50
+ if (typeof platformEntry === 'string') {
51
+ return [platformEntry]
52
+ }
53
+
54
+ const order = detectLinuxLibc() === 'musl' ? ['musl', 'glibc'] : ['glibc', 'musl']
55
+ return order.map((libc) => platformEntry[libc])
56
+ }
57
+
58
+ /**
59
+ * Split a specifier from {@link getBinCandidates} into the package that ships
60
+ * the binary and the binary's path inside it.
61
+ *
62
+ * @param {string} specifier
63
+ * @returns {{ packageName: string, binFile: string }}
64
+ */
65
+ export function splitBinSpecifier (specifier) {
66
+ const [scope, name, ...rest] = specifier.split('/')
67
+ return { packageName: `${scope}/${name}`, binFile: rest.join('/') }
68
+ }
69
+
70
+ /**
71
+ * Path to the native binary of whichever platform package the package manager
72
+ * installed, or `null` when none is present (Corepack, `--no-optional`).
73
+ *
74
+ * @returns {string | null}
75
+ */
76
+ export function resolveInstalledBinary () {
77
+ // Use whichever platform package the package manager installed: it already
78
+ // filtered by `os`/`cpu`/`libc`, more reliable than re-deriving the host.
79
+ for (const specifier of getBinCandidates()) {
80
+ try {
81
+ return require.resolve(specifier)
82
+ } catch {}
83
+ }
84
+ return null
85
+ }
86
+
87
+ // A successful read with no optionalDependencies is the dev checkout (there is
88
+ // no native binary to link there); a read/parse failure is a corrupt published
89
+ // package and must not be silently swallowed into that same path.
90
+ export function readWrapperManifest () {
91
+ const manifestPath = path.join(wrapperDir, 'package.json')
92
+ let manifest
93
+ try {
94
+ manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'))
95
+ } catch (err) {
96
+ throw new Error(`Failed to read ${manifestPath}: ${err.message}`)
97
+ }
98
+ if (typeof manifest !== 'object' || manifest == null || Array.isArray(manifest)) {
99
+ throw new Error(`Expected ${manifestPath} to contain a JSON object`)
100
+ }
101
+ return manifest
102
+ }
103
+
104
+ function detectLinuxLibc () {
105
+ if (platform !== 'linux') {
106
+ return null
107
+ }
108
+
109
+ // glibc builds set `glibcVersionRuntime`; musl leaves it unset. Guarded —
110
+ // `process.report` may be unavailable, leaving ordering to the default.
111
+ try {
112
+ return process.report?.getReport().header.glibcVersionRuntime ? 'glibc' : 'musl'
113
+ } catch {
114
+ return null
115
+ }
116
+ }
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "./dist/node_modules/node-gyp/gyp/gyp"
10
10
  ]
11
11
  },
12
- "version": "12.0.0-rc.0",
12
+ "version": "12.0.0-rc.10",
13
13
  "description": "Fast, disk space efficient package manager",
14
14
  "keywords": [
15
15
  "pnpm",
@@ -39,18 +39,21 @@
39
39
  "pn",
40
40
  "pnpx",
41
41
  "pnx",
42
+ "bin/",
42
43
  "install.js",
43
- "dist/"
44
+ "native-binary.mjs",
45
+ "dist/",
46
+ "THIRD-PARTY-NOTICES.md"
44
47
  ],
45
48
  "optionalDependencies": {
46
- "@pnpm/exe.win32-x64": "12.0.0-rc.0",
47
- "@pnpm/exe.win32-arm64": "12.0.0-rc.0",
48
- "@pnpm/exe.darwin-x64": "12.0.0-rc.0",
49
- "@pnpm/exe.darwin-arm64": "12.0.0-rc.0",
50
- "@pnpm/exe.linux-x64": "12.0.0-rc.0",
51
- "@pnpm/exe.linux-arm64": "12.0.0-rc.0",
52
- "@pnpm/exe.linux-x64-musl": "12.0.0-rc.0",
53
- "@pnpm/exe.linux-arm64-musl": "12.0.0-rc.0"
49
+ "@pnpm/exe.win32-x64": "12.0.0-rc.10",
50
+ "@pnpm/exe.win32-arm64": "12.0.0-rc.10",
51
+ "@pnpm/exe.darwin-x64": "12.0.0-rc.10",
52
+ "@pnpm/exe.darwin-arm64": "12.0.0-rc.10",
53
+ "@pnpm/exe.linux-x64": "12.0.0-rc.10",
54
+ "@pnpm/exe.linux-arm64": "12.0.0-rc.10",
55
+ "@pnpm/exe.linux-x64-musl": "12.0.0-rc.10",
56
+ "@pnpm/exe.linux-arm64-musl": "12.0.0-rc.10"
54
57
  },
55
58
  "scripts": {
56
59
  "preinstall": "node install.js",