Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions lib/commands/exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,16 @@ class Exec extends BaseCommand {
}
}

async callExec (args, { name, locationMsg, runPath } = {}) {
async callExec (args, { locationMsg, runPath } = {}) {
let localBin = this.npm.localBin
let pkgPath = this.npm.localPrefix

// This is where libnpmexec will actually run the scripts from
if (!runPath) {
runPath = process.cwd()
} else {
// We have to consider if the workspace has its own separate versions libnpmexec will walk up to localDir after looking here
localBin = resolve(this.npm.localDir, name, 'node_modules', '.bin')
// Use the workspace's own node_modules/.bin, not localDir/<name>, since the linked strategy does not symlink workspaces into the root node_modules.
localBin = resolve(runPath, 'node_modules', '.bin')
// We also need to look for `bin` entries in the workspace package.json
// libnpmexec will NOT look in the project root for the bin entry
pkgPath = runPath
Expand Down
35 changes: 35 additions & 0 deletions test/lib/commands/exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,41 @@ t.test('finds workspace dep first', async t => {
t.ok(exists.isFile(), 'bin ran, creating file')
})

t.test('finds workspace dep bin under linked install strategy', async t => {
const { npm } = await loadMockNpm(t, {
config: {
'install-strategy': 'linked',
},
prefixDir: {
'package.json': JSON.stringify({
name: '@npmcli/npx-workspace-root-test',
workspaces: ['workspace-a', 'tool'],
}),
'workspace-a': {
'package.json': JSON.stringify({
name: 'workspace-a',
dependencies: { tool: '*' },
}),
},
tool: {
'package.json': JSON.stringify({
name: 'tool',
version: '1.0.0',
bin: { 'npx-test': 'index.js' },
}),
'index.js': `#!/usr/bin/env node
require('fs').writeFileSync('npm-exec-test-success', '')`,
},
},
})

await npm.exec('install', [])
npm.config.set('workspace', ['workspace-a'])
await npm.exec('exec', ['npx-test'])
const exists = await fs.stat(path.join(npm.prefix, 'workspace-a', 'npm-exec-test-success'))
t.ok(exists.isFile(), 'workspace-local bin ran instead of falling back to the registry')
})

t.test('npx --no-install @npmcli/npx-test', async t => {
const registry = new MockRegistry({
tap: t,
Expand Down
Loading