@pnpm/pnpr 0.0.0-26062401 → 0.0.0-26070201

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 (3) hide show
  1. package/bin/pnpr +4 -76
  2. package/install.js +178 -0
  3. package/package.json +14 -9
package/bin/pnpr CHANGED
@@ -1,76 +1,4 @@
1
- #!/usr/bin/env node
2
- const { platform, arch, env } = process;
3
-
4
- const PLATFORMS = {
5
- win32: {
6
- x64: "@pnpm/pnpr.win32-x64/pnpr.exe",
7
- arm64: "@pnpm/pnpr.win32-arm64/pnpr.exe",
8
- },
9
- darwin: {
10
- x64: "@pnpm/pnpr.darwin-x64/pnpr",
11
- arm64: "@pnpm/pnpr.darwin-arm64/pnpr",
12
- },
13
- linux: {
14
- x64: {
15
- glibc: "@pnpm/pnpr.linux-x64/pnpr",
16
- musl: "@pnpm/pnpr.linux-x64-musl/pnpr",
17
- },
18
- arm64: {
19
- glibc: "@pnpm/pnpr.linux-arm64/pnpr",
20
- musl: "@pnpm/pnpr.linux-arm64-musl/pnpr",
21
- },
22
- },
23
- };
24
-
25
- const binPath = getBinPath();
26
- if (binPath) {
27
- const result = require("child_process").spawnSync(
28
- require.resolve(binPath),
29
- process.argv.slice(2),
30
- {
31
- shell: false,
32
- stdio: "inherit",
33
- env,
34
- }
35
- );
36
-
37
- if (result.error) {
38
- throw result.error;
39
- }
40
-
41
- // result.status is null when the child was killed by a signal; falling
42
- // through to `exitCode = null` would make the wrapper appear to exit 0
43
- // and mask the signal. Re-raise the signal so the parent terminates
44
- // the same way; fall back to a non-zero exit if that's not possible.
45
- if (typeof result.status === "number") {
46
- process.exitCode = result.status;
47
- } else if (result.signal) {
48
- process.kill(process.pid, result.signal);
49
- } else {
50
- process.exitCode = 1;
51
- }
52
- } else {
53
- console.error(
54
- "The @pnpm/pnpr package doesn't ship with prebuilt binaries for your platform yet. " +
55
- "You can create an issue at https://github.com/pnpm/pnpm/issues for support."
56
- );
57
- process.exitCode = 1;
58
- }
59
-
60
- function getBinPath() {
61
- const platformEntry = PLATFORMS?.[platform]?.[arch];
62
-
63
- if (platformEntry == null || typeof platformEntry === "string") {
64
- return platformEntry;
65
- }
66
-
67
- return platformEntry[detectLinuxLibc()];
68
- }
69
-
70
- function detectLinuxLibc() {
71
- if (platform !== "linux") {
72
- return null;
73
- }
74
-
75
- return process.report.getReport().header.glibcVersionRuntime ? "glibc" : "musl";
76
- }
1
+ This is a placeholder. pnpr'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/pnpr's build under pnpm or Bun, or drop --ignore-scripts).
package/install.js ADDED
@@ -0,0 +1,178 @@
1
+ #!/usr/bin/env node
2
+ // Preinstall: replace the placeholder `bin/pnpr` with the platform's native
3
+ // binary, so the command runs the binary directly instead of paying Node.js
4
+ // startup on every call. Mirrors how `@pnpm/exe` ships pnpm.
5
+ //
6
+ // The published `bin/pnpr` is a shebang-less placeholder: the Windows `.bin`
7
+ // shim is generated from the bin file, so a Node launcher there would bake in a
8
+ // `node bin/pnpr` call this script cannot rewrite (npm does not re-read
9
+ // package.json after preinstall). The cost is that there is no fallback — when
10
+ // build scripts are blocked (`--ignore-scripts`, pnpm/Bun defaults) the
11
+ // placeholder stays until the build is allow-listed.
12
+ import console from 'node:console'
13
+ import fs from 'node:fs'
14
+ import { createRequire } from 'node:module'
15
+ import path from 'node:path'
16
+ import process from 'node:process'
17
+ import { fileURLToPath } from 'node:url'
18
+
19
+ const require = createRequire(import.meta.url)
20
+ const ownDir = path.dirname(fileURLToPath(import.meta.url))
21
+ const { platform, arch } = process
22
+
23
+ const PLATFORMS = {
24
+ win32: {
25
+ x64: '@pnpm/pnpr.win32-x64/pnpr.exe',
26
+ arm64: '@pnpm/pnpr.win32-arm64/pnpr.exe',
27
+ },
28
+ darwin: {
29
+ x64: '@pnpm/pnpr.darwin-x64/pnpr',
30
+ arm64: '@pnpm/pnpr.darwin-arm64/pnpr',
31
+ },
32
+ linux: {
33
+ x64: {
34
+ glibc: '@pnpm/pnpr.linux-x64/pnpr',
35
+ musl: '@pnpm/pnpr.linux-x64-musl/pnpr',
36
+ },
37
+ arm64: {
38
+ glibc: '@pnpm/pnpr.linux-arm64/pnpr',
39
+ musl: '@pnpm/pnpr.linux-arm64-musl/pnpr',
40
+ },
41
+ },
42
+ }
43
+
44
+ setup()
45
+
46
+ function setup () {
47
+ const candidates = getBinCandidates()
48
+ if (candidates.length === 0) {
49
+ fail(`@pnpm/pnpr does not ship a prebuilt binary for ${platform}-${arch}.`)
50
+ }
51
+
52
+ // Use whichever platform package the package manager installed: it already
53
+ // filtered by `os`/`cpu`/`libc`, more reliable than re-deriving the host.
54
+ let nativeBinary
55
+ for (const target of candidates) {
56
+ try {
57
+ nativeBinary = require.resolve(target)
58
+ break
59
+ } catch {
60
+ // Not installed for this host; try the next candidate.
61
+ }
62
+ }
63
+ if (nativeBinary == null) {
64
+ const pkgName = candidates[0].split('/').slice(0, 2).join('/')
65
+ fail(
66
+ `The "${pkgName}" package is not installed, so pnpr has no native binary to run.\n` +
67
+ 'If your package manager skipped optional dependencies or blocked build scripts, ' +
68
+ 'enable them and reinstall.'
69
+ )
70
+ }
71
+
72
+ const binDir = path.join(ownDir, 'bin')
73
+ if (platform === 'win32') {
74
+ // The existing shim points at `bin/pnpr`, so that file must become the
75
+ // binary; the `.exe` twin and `bin` rewrite are for shims generated later.
76
+ placeBinary(nativeBinary, path.join(binDir, 'pnpr.exe'))
77
+ placeBinary(nativeBinary, path.join(binDir, 'pnpr'))
78
+ rewriteBin('bin/pnpr.exe')
79
+ } else {
80
+ placeBinary(nativeBinary, path.join(binDir, 'pnpr'), 0o755)
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Atomically place `nativeBinary` at `destPath` (hard link, falling back to a
86
+ * copy across filesystems, via a temp file + rename). Exits the process on
87
+ * failure — without the binary there is no working `pnpr`.
88
+ *
89
+ * @param {string} nativeBinary Absolute path to the resolved native binary.
90
+ * @param {string} destPath Absolute path to create.
91
+ * @param {number} [mode] chmod for the copy path only; a hard link shares the
92
+ * source inode (the shared store blob under pnpm), so its mode must not change.
93
+ */
94
+ function placeBinary (nativeBinary, destPath, mode) {
95
+ const tempPath = `${destPath}.pnpr-tmp`
96
+ try {
97
+ fs.rmSync(tempPath, { force: true })
98
+ let linked = false
99
+ try {
100
+ fs.linkSync(nativeBinary, tempPath)
101
+ linked = true
102
+ } catch {
103
+ fs.copyFileSync(nativeBinary, tempPath)
104
+ }
105
+ if (!linked && mode != null) {
106
+ fs.chmodSync(tempPath, mode)
107
+ }
108
+ fs.renameSync(tempPath, destPath)
109
+ } catch (err) {
110
+ try {
111
+ fs.rmSync(tempPath, { force: true })
112
+ } catch {
113
+ // Nothing to clean up.
114
+ }
115
+ fail(`Could not install the pnpr binary at ${destPath}: ${err.message}`)
116
+ }
117
+ }
118
+
119
+ function rewriteBin (binValue) {
120
+ const pkgJsonPath = path.join(ownDir, 'package.json')
121
+ // Write a fresh file and rename it over package.json rather than truncating in
122
+ // place: pnpm hard-links package.json from its content-addressable store, so an
123
+ // in-place write would mutate the shared store blob. Best-effort — it only
124
+ // helps shims generated later.
125
+ const tempPath = `${pkgJsonPath}.pnpr-tmp`
126
+ try {
127
+ const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'))
128
+ pkg.bin = binValue
129
+ fs.writeFileSync(tempPath, JSON.stringify(pkg, null, 2))
130
+ fs.renameSync(tempPath, pkgJsonPath)
131
+ } catch {
132
+ try {
133
+ fs.rmSync(tempPath, { force: true })
134
+ } catch {
135
+ // Nothing to clean up.
136
+ }
137
+ }
138
+ }
139
+
140
+ function fail (message) {
141
+ console.error(message)
142
+ process.exit(1)
143
+ }
144
+
145
+ /**
146
+ * Native binary specifiers to try, most-preferred first; empty when the host is
147
+ * unsupported. The linux glibc/musl pair is ordered by detected libc, which
148
+ * only decides the winner when both are installed (e.g. `npm install --force`).
149
+ *
150
+ * @returns {string[]}
151
+ */
152
+ function getBinCandidates () {
153
+ const platformEntry = PLATFORMS?.[platform]?.[arch]
154
+
155
+ if (platformEntry == null) {
156
+ return []
157
+ }
158
+ if (typeof platformEntry === 'string') {
159
+ return [platformEntry]
160
+ }
161
+
162
+ const order = detectLinuxLibc() === 'musl' ? ['musl', 'glibc'] : ['glibc', 'musl']
163
+ return order.map((libc) => platformEntry[libc])
164
+ }
165
+
166
+ function detectLinuxLibc () {
167
+ if (platform !== 'linux') {
168
+ return null
169
+ }
170
+
171
+ // glibc builds set `glibcVersionRuntime`; musl leaves it unset. Guarded —
172
+ // `process.report` may be unavailable, leaving ordering to the default.
173
+ try {
174
+ return process.report?.getReport().header.glibcVersionRuntime ? 'glibc' : 'musl'
175
+ } catch {
176
+ return null
177
+ }
178
+ }
package/package.json CHANGED
@@ -14,23 +14,28 @@
14
14
  "url": "https://github.com/pnpm/pnpm",
15
15
  "directory": "pnpr/npm/pnpr"
16
16
  },
17
+ "type": "module",
17
18
  "engines": {
18
19
  "node": ">=18.*"
19
20
  },
20
21
  "files": [
21
22
  "bin/pnpr",
23
+ "install.js",
22
24
  "LICENSE.md"
23
25
  ],
24
- "version": "0.0.0-26062401",
26
+ "version": "0.0.0-26070201",
25
27
  "optionalDependencies": {
26
- "@pnpm/pnpr.win32-x64": "0.0.0-26062401",
27
- "@pnpm/pnpr.win32-arm64": "0.0.0-26062401",
28
- "@pnpm/pnpr.darwin-x64": "0.0.0-26062401",
29
- "@pnpm/pnpr.darwin-arm64": "0.0.0-26062401",
30
- "@pnpm/pnpr.linux-x64": "0.0.0-26062401",
31
- "@pnpm/pnpr.linux-arm64": "0.0.0-26062401",
32
- "@pnpm/pnpr.linux-x64-musl": "0.0.0-26062401",
33
- "@pnpm/pnpr.linux-arm64-musl": "0.0.0-26062401"
28
+ "@pnpm/pnpr.win32-x64": "0.0.0-26070201",
29
+ "@pnpm/pnpr.win32-arm64": "0.0.0-26070201",
30
+ "@pnpm/pnpr.darwin-x64": "0.0.0-26070201",
31
+ "@pnpm/pnpr.darwin-arm64": "0.0.0-26070201",
32
+ "@pnpm/pnpr.linux-x64": "0.0.0-26070201",
33
+ "@pnpm/pnpr.linux-arm64": "0.0.0-26070201",
34
+ "@pnpm/pnpr.linux-x64-musl": "0.0.0-26070201",
35
+ "@pnpm/pnpr.linux-arm64-musl": "0.0.0-26070201"
36
+ },
37
+ "scripts": {
38
+ "preinstall": "node install.js"
34
39
  },
35
40
  "bin": {
36
41
  "pnpr": "bin/pnpr"