|
1 | | -import { promises as fs, realpathSync, statSync } from 'node:fs' |
| 1 | +import { existsSync, promises as fs, realpathSync, statSync } from 'node:fs' |
2 | 2 | import path from 'node:path' |
3 | 3 | import process from 'node:process' |
4 | 4 |
|
@@ -191,30 +191,39 @@ export function findBinPathDetailsSync(binName: string): { |
191 | 191 | } |
192 | 192 |
|
193 | 193 | export function findNpmPathSync(npmBinPath: string): string | undefined { |
194 | | - let curPath = npmBinPath |
| 194 | + let thePath = npmBinPath |
195 | 195 | while (true) { |
| 196 | + const nmPath = path.join(thePath, NODE_MODULES) |
196 | 197 | if ( |
197 | 198 | // npm bin paths may look like: |
198 | 199 | // /usr/local/share/npm/bin/npm |
199 | 200 | // /Users/SomeUsername/.nvm/versions/node/vX.X.X/bin/npm |
200 | 201 | // C:\Users\SomeUsername\AppData\Roaming\npm\bin\npm.cmd |
201 | 202 | // OR |
202 | 203 | // C:\Program Files\nodejs\npm.cmd |
203 | | - path.basename(curPath) === NPM || |
| 204 | + // |
204 | 205 | // In all cases the npm path contains a node_modules folder: |
205 | 206 | // /usr/local/share/npm/bin/npm/node_modules |
206 | 207 | // C:\Program Files\nodejs\node_modules |
207 | | - statSync(path.join(curPath, NODE_MODULES), { |
208 | | - throwIfNoEntry: false |
209 | | - })?.isDirectory() |
| 208 | + // |
| 209 | + // Use existsSync here because statsSync, even with { throwIfNoEntry: false }, |
| 210 | + // will throw an ENOTDIR error for paths like ./a-file-that-exists/a-directory-that-does-not. |
| 211 | + // See https://github.com/nodejs/node/issues/56993. |
| 212 | + existsSync(nmPath) && |
| 213 | + statSync(nmPath, { throwIfNoEntry: false })?.isDirectory() && |
| 214 | + // Optimistically look for the default location. |
| 215 | + (path.basename(thePath) === NPM || |
| 216 | + // Chocolatey installs npm bins in the same directory as node bins. |
| 217 | + // Lazily access constants.WIN32. |
| 218 | + (constants.WIN32 && existsSync(path.join(thePath, `${NPM}.cmd`)))) |
210 | 219 | ) { |
211 | | - return curPath |
| 220 | + return thePath |
212 | 221 | } |
213 | | - const parent = path.dirname(curPath) |
214 | | - if (parent === curPath) { |
| 222 | + const parent = path.dirname(thePath) |
| 223 | + if (parent === thePath) { |
215 | 224 | return undefined |
216 | 225 | } |
217 | | - curPath = parent |
| 226 | + thePath = parent |
218 | 227 | } |
219 | 228 | } |
220 | 229 |
|
|
0 commit comments