From 7f1ab8822a8d50403338595ab9f218e4d63f37fa Mon Sep 17 00:00:00 2001 From: Gar Date: Thu, 7 Mar 2024 12:53:49 -0800 Subject: [PATCH] fix: more lightweight npm bin discovery in windows (#7271) This will stop npm having to load twice on every windows invocation --- bin/npm | 3 ++- bin/npm-prefix.js | 30 ++++++++++++++++++++++++++++++ bin/npm.cmd | 3 ++- bin/npm.ps1 | 4 ++-- bin/npx | 4 ++-- bin/npx.cmd | 4 ++-- bin/npx.ps1 | 4 ++-- test/bin/windows-shims.js | 15 ++++++--------- 8 files changed, 48 insertions(+), 19 deletions(-) create mode 100755 bin/npm-prefix.js diff --git a/bin/npm b/bin/npm index 7f210b936e1fa..027dc9d128d22 100755 --- a/bin/npm +++ b/bin/npm @@ -41,8 +41,9 @@ if [ $? -ne 0 ]; then fi no_node_dir fi +NPM_PREFIX_JS="$CLI_BASEDIR/node_modules/npm/bin/npm-prefix.js" NPM_CLI_JS="$CLI_BASEDIR/node_modules/npm/bin/npm-cli.js" -NPM_PREFIX=`"$NODE_EXE" "$NPM_CLI_JS" prefix -g` +NPM_PREFIX=`"$NODE_EXE" "$NPM_PREFIX_JS"` if [ $? -ne 0 ]; then no_node_dir fi diff --git a/bin/npm-prefix.js b/bin/npm-prefix.js new file mode 100755 index 0000000000000..3ff43de0dd84d --- /dev/null +++ b/bin/npm-prefix.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node +// This is a single-use bin to help windows discover the proper prefix for npm +// without having to load all of npm first +// It does not accept argv params + +const path = require('path') +const Config = require('@npmcli/config') +const { definitions, flatten, shorthands } = require('@npmcli/config/lib/definitions') +const config = new Config({ + npmPath: path.dirname(__dirname), + // argv is explicitly not looked at since prefix is not something that can be changed via argv + argv: [], + definitions, + flatten, + shorthands, + excludeNpmCwd: false, +}) + +async function main () { + try { + await config.load() + // eslint-disable-next-line no-console + console.log(config.globalPrefix) + } catch (err) { + // eslint-disable-next-line no-console + console.error(err) + process.exit(1) + } +} +main() diff --git a/bin/npm.cmd b/bin/npm.cmd index 880554dcdd686..68af4b0fca09f 100755 --- a/bin/npm.cmd +++ b/bin/npm.cmd @@ -8,8 +8,9 @@ IF NOT EXIST "%NODE_EXE%" ( SET "NODE_EXE=node" ) +SET "NPM_PREFIX_JS=%~dp0\node_modules\npm\bin\npm-prefix.js" SET "NPM_CLI_JS=%~dp0\node_modules\npm\bin\npm-cli.js" -FOR /F "delims=" %%F IN ('CALL "%NODE_EXE%" "%NPM_CLI_JS%" prefix -g') DO ( +FOR /F "delims=" %%F IN ('CALL "%NODE_EXE%" "%NPM_PREFIX_JS%"') DO ( SET "NPM_PREFIX_NPM_CLI_JS=%%F\node_modules\npm\bin\npm-cli.js" ) IF EXIST "%NPM_PREFIX_NPM_CLI_JS%" ( diff --git a/bin/npm.ps1 b/bin/npm.ps1 index f2f236adc23db..399e33360e853 100644 --- a/bin/npm.ps1 +++ b/bin/npm.ps1 @@ -17,8 +17,8 @@ if ($nodebin -eq $null) { } $nodedir = $(New-Object -ComObject Scripting.FileSystemObject).GetFile("$nodebin").ParentFolder.Path -$npmclijs="$nodedir/node_modules/npm/bin/npm-cli.js" -$npmprefix=(& $nodeexe $npmclijs prefix -g) +$npmprefixjs="$nodedir/node_modules/npm/bin/npm-prefix.js" +$npmprefix=(& $nodeexe $npmprefixjs) if ($LASTEXITCODE -ne 0) { Write-Host "Could not determine Node.js install directory" exit 1 diff --git a/bin/npx b/bin/npx index 719ff8ecdc19b..b8619ee9c5e37 100755 --- a/bin/npx +++ b/bin/npx @@ -41,9 +41,9 @@ if [ $? -ne 0 ]; then fi no_node_dir fi -NPM_CLI_JS="$CLI_BASEDIR/node_modules/npm/bin/npm-cli.js" +NPM_PREFIX_JS="$CLI_BASEDIR/node_modules/npm/bin/npm-prefix.js" NPX_CLI_JS="$CLI_BASEDIR/node_modules/npm/bin/npx-cli.js" -NPM_PREFIX=`"$NODE_EXE" "$NPM_CLI_JS" prefix -g` +NPM_PREFIX=`"$NODE_EXE" "$NPM_PREFIX_JS"` if [ $? -ne 0 ]; then no_node_dir fi diff --git a/bin/npx.cmd b/bin/npx.cmd index 9339ebd065282..ab991abfc2562 100755 --- a/bin/npx.cmd +++ b/bin/npx.cmd @@ -8,9 +8,9 @@ IF NOT EXIST "%NODE_EXE%" ( SET "NODE_EXE=node" ) -SET "NPM_CLI_JS=%~dp0\node_modules\npm\bin\npm-cli.js" +SET "NPM_PREFIX_JS=%~dp0\node_modules\npm\bin\npm-prefix.js" SET "NPX_CLI_JS=%~dp0\node_modules\npm\bin\npx-cli.js" -FOR /F "delims=" %%F IN ('CALL "%NODE_EXE%" "%NPM_CLI_JS%" prefix -g') DO ( +FOR /F "delims=" %%F IN ('CALL "%NODE_EXE%" "%NPM_PREFIX_JS%"') DO ( SET "NPM_PREFIX_NPX_CLI_JS=%%F\node_modules\npm\bin\npx-cli.js" ) IF EXIST "%NPM_PREFIX_NPX_CLI_JS%" ( diff --git a/bin/npx.ps1 b/bin/npx.ps1 index 437e2a7b74c3a..1d59fc52083d7 100644 --- a/bin/npx.ps1 +++ b/bin/npx.ps1 @@ -17,8 +17,8 @@ if ($nodebin -eq $null) { } $nodedir = $(New-Object -ComObject Scripting.FileSystemObject).GetFile("$nodebin").ParentFolder.Path -$npmclijs="$nodedir/node_modules/npm/bin/npm-cli.js" -$npmprefix=(& $nodeexe $npmclijs prefix -g) +$npmprefixjs="$nodedir/node_modules/npm/bin/npm-prefix.js" +$npmprefix=(& $nodeexe $npmprefixjs) if ($LASTEXITCODE -ne 0) { Write-Host "Could not determine Node.js install directory" exit 1 diff --git a/test/bin/windows-shims.js b/test/bin/windows-shims.js index 5fa6ff142b737..2abe5013bf10b 100644 --- a/test/bin/windows-shims.js +++ b/test/bin/windows-shims.js @@ -44,23 +44,21 @@ t.test('shim contents', t => { t.test('bash', t => { const { diff, letters } = diffFiles(SHIMS.npm, SHIMS.npx) - t.match(diff[0].split('\n').reverse().join(''), /^NPX_CLI_JS=/, 'has NPX_CLI') - t.equal(diff.length, 1) + t.strictSame(diff, []) t.strictSame([...letters], ['M', 'X'], 'all other changes are m->x') t.end() }) t.test('cmd', t => { const { diff, letters } = diffFiles(SHIMS['npm.cmd'], SHIMS['npx.cmd']) - t.match(diff[0], /^SET "NPX_CLI_JS=/, 'has NPX_CLI') - t.equal(diff.length, 1) + t.strictSame(diff, []) t.strictSame([...letters], ['M', 'X'], 'all other changes are m->x') t.end() }) t.test('pwsh', t => { const { diff, letters } = diffFiles(SHIMS['npm.ps1'], SHIMS['npx.ps1']) - t.equal(diff.length, 0) + t.strictSame(diff, []) t.strictSame([...letters], ['M', 'X'], 'all other changes are m->x') t.end() }) @@ -96,13 +94,12 @@ t.test('run shims', t => { node_modules: { npm: { bin: { - 'npx-cli.js': `throw new Error('this should not be called')`, - 'npm-cli.js': ` - const assert = require('assert') + 'npm-prefix.js': ` const { resolve } = require('path') - assert.equal(process.argv.slice(2).join(' '), 'prefix -g') console.log(resolve(__dirname, '../../../global-prefix')) `, + 'npx-cli.js': `throw new Error('local npx should not be called')`, + 'npm-cli.js': `throw new Error('local npm should not be called')`, }, }, },