@pnpm/exe 12.0.0-rc.4 → 12.0.0-rc.6

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/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.4",
12
+ "version": "12.0.0-rc.6",
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.4",
47
- "@pnpm/exe.win32-arm64": "12.0.0-rc.4",
48
- "@pnpm/exe.darwin-x64": "12.0.0-rc.4",
49
- "@pnpm/exe.darwin-arm64": "12.0.0-rc.4",
50
- "@pnpm/exe.linux-x64": "12.0.0-rc.4",
51
- "@pnpm/exe.linux-arm64": "12.0.0-rc.4",
52
- "@pnpm/exe.linux-x64-musl": "12.0.0-rc.4",
53
- "@pnpm/exe.linux-arm64-musl": "12.0.0-rc.4"
49
+ "@pnpm/exe.win32-x64": "12.0.0-rc.6",
50
+ "@pnpm/exe.win32-arm64": "12.0.0-rc.6",
51
+ "@pnpm/exe.darwin-x64": "12.0.0-rc.6",
52
+ "@pnpm/exe.darwin-arm64": "12.0.0-rc.6",
53
+ "@pnpm/exe.linux-x64": "12.0.0-rc.6",
54
+ "@pnpm/exe.linux-arm64": "12.0.0-rc.6",
55
+ "@pnpm/exe.linux-x64-musl": "12.0.0-rc.6",
56
+ "@pnpm/exe.linux-arm64-musl": "12.0.0-rc.6"
54
57
  },
55
58
  "scripts": {
56
59
  "preinstall": "node install.js",