Skip to content

Commit 2a9292c

Browse files
committed
fix: global bin discovery fixed if found on any level globally
1 parent 1fdf327 commit 2a9292c

File tree

3 files changed

+75
-4
lines changed

3 files changed

+75
-4
lines changed

workspaces/libnpmexec/lib/index.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,13 @@ const exec = async (opts) => {
203203
const globalTree = await globalArb.loadActual()
204204
const { manifest: globalManifest, node: globalNode } =
205205
await missingFromTree({ spec, tree: globalTree, flatOptions })
206-
if (globalNode) {
207-
const newPath = globalNode.binPaths.filter(p => p.endsWith(args[0]))[0]
208-
binPaths.push(newPath.replace(args[0], ''))
206+
// check for the bin in the global tree at any level deep
207+
// if we found a node matched with spec, we can use it to get the bin path from it
208+
const matchingBinPaths = globalNode
209+
?.binPaths.filter(binPath => binPath.endsWith(args[0]))
210+
211+
if (matchingBinPaths?.length && await fileExists(matchingBinPaths[0])) {
212+
binPaths.push(dirname(matchingBinPaths[0]))
209213
return await run()
210214
}
211215
if (!globalManifest && await fileExists(`${globalBin}/${args[0]}`)) {

workspaces/libnpmexec/test/fixtures/setup.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,8 @@ const setup = (t, {
224224
}
225225
await binLinks({
226226
pkg: binPkg,
227-
path: resolve(path, nodeModules, binPkg.name),
227+
// include pkg.path for nested bin links support
228+
path: resolve(path, nodeModules, binPkg.path || binPkg.name),
228229
})
229230
},
230231
readOutput: async (outputPath, { root = path } = {}) => {

workspaces/libnpmexec/test/local.js

+66
Original file line numberDiff line numberDiff line change
@@ -370,3 +370,69 @@ t.test('global scoped pkg', async t => {
370370
created: 'global/node_modules/@npmcli/create-test/bin-file.js',
371371
})
372372
})
373+
t.test('global scoped pkg - new', async t => {
374+
const pkgA1 = createPkg({
375+
localVersion: '1.0.0',
376+
name: '@npmcli/A',
377+
})
378+
379+
const pkgA2 = createPkg({
380+
localVersion: '2.0.0',
381+
name: '@npmcli/A',
382+
})
383+
384+
const pkgB = createPkg({
385+
localVersion: '1.0.0',
386+
name: '@npmcli/B',
387+
})
388+
389+
const pkgBfix = merge(pkgB.fixtures, {
390+
node_modules: {
391+
'@npmcli': { B: {
392+
node_modules: {
393+
'@npmcli': {
394+
A: pkgA2.fixtures.packages['@npmcli-A-2.0.0'],
395+
} },
396+
'package.json': { dependencies: { '@npmcli/A': '2.0.0' } },
397+
},
398+
},
399+
} })
400+
401+
const { chmod, exec, readOutput, binLinks, registry, path } = setup(t, {
402+
pkg: [pkgA2.pkg, pkgA1.pkg, pkgB.pkg],
403+
global: true,
404+
testdir: merge(pkgA1.fixtures, pkgBfix),
405+
})
406+
407+
await chmod()
408+
await chmod('global/node_modules/@npmcli/B/node_modules/@npmcli/A/bin-file.js')
409+
await binLinks()
410+
await binLinks({
411+
name: '@npmcli/A',
412+
path: '@npmcli/B/node_modules/@npmcli/A',
413+
bin: { A: 'bin-file.js' },
414+
})
415+
416+
await pkgA2.package({ registry, path, times: 1, tarballs: [] })
417+
await pkgA1.package({ registry, path, times: 1, tarballs: [] })
418+
419+
await exec({
420+
args: ['@npmcli/A@2.0.0'],
421+
})
422+
423+
t.match(await readOutput('@npmcli-A'), {
424+
value: 'packages-2.0.0',
425+
args: [],
426+
created: 'global/node_modules/@npmcli/B/node_modules/@npmcli/A/bin-file.js',
427+
})
428+
429+
await exec({
430+
args: ['@npmcli/A@1.0.0'],
431+
})
432+
433+
t.match(await readOutput('@npmcli-A'), {
434+
value: 'local-1.0.0',
435+
args: [],
436+
created: 'global/node_modules/@npmcli/A/bin-file.js',
437+
})
438+
})

0 commit comments

Comments
 (0)