Skip to content

Commit

Permalink
fix: more lightweight npm bin discovery in windows (#7271)
Browse files Browse the repository at this point in the history
This will stop npm having to load twice on every windows invocation
  • Loading branch information
wraithgar authored Mar 7, 2024
1 parent 0dab381 commit 7f1ab88
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 19 deletions.
3 changes: 2 additions & 1 deletion bin/npm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 30 additions & 0 deletions bin/npm-prefix.js
Original file line number Diff line number Diff line change
@@ -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()
3 changes: 2 additions & 1 deletion bin/npm.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -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%" (
Expand Down
4 changes: 2 additions & 2 deletions bin/npm.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions bin/npx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions bin/npx.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -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%" (
Expand Down
4 changes: 2 additions & 2 deletions bin/npx.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 6 additions & 9 deletions test/bin/windows-shims.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()
})
Expand Down Expand Up @@ -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')`,
},
},
},
Expand Down

0 comments on commit 7f1ab88

Please sign in to comment.