@@ -73,6 +73,11 @@ const missingFromTree = async ({ spec, tree, flatOptions, isNpxTree }) => {
73
73
}
74
74
}
75
75
76
+ // see if the package.json at `path` has an entry that matches `cmd`
77
+ const hasPkgBin = ( path , cmd , flatOptions ) =>
78
+ pacote . manifest ( path , flatOptions )
79
+ . then ( manifest => manifest ?. bin ?. [ cmd ] ) . catch ( ( ) => null )
80
+
76
81
const exec = async ( opts ) => {
77
82
const {
78
83
args = [ ] ,
@@ -89,6 +94,13 @@ const exec = async (opts) => {
89
94
...flatOptions
90
95
} = opts
91
96
97
+ let pkgPaths = opts . pkgPath
98
+ if ( typeof pkgPaths === 'string' ) {
99
+ pkgPaths = [ pkgPaths ]
100
+ }
101
+ if ( ! pkgPaths ) {
102
+ pkgPaths = [ '.' ]
103
+ }
92
104
let yes = opts . yes
93
105
const run = ( ) => runScript ( {
94
106
args,
@@ -106,28 +118,31 @@ const exec = async (opts) => {
106
118
return run ( )
107
119
}
108
120
121
+ // Look in the local tree too
122
+ pkgPaths . push ( path )
123
+
109
124
let needPackageCommandSwap = ( args . length > 0 ) && ( packages . length === 0 )
110
125
// If they asked for a command w/o specifying a package, see if there is a
111
126
// bin that directly matches that name:
112
- // - in the local package itself
113
- // - in the local tree
127
+ // - in any local packages (pkgPaths can have workspaces in them or just the root)
128
+ // - in the local tree (path)
114
129
// - globally
115
130
if ( needPackageCommandSwap ) {
116
- let localManifest
117
- try {
118
- localManifest = await pacote . manifest ( path , flatOptions )
119
- } catch {
120
- // no local package.json? no problem, move one.
131
+ // Local packages and local tree
132
+ for ( const p of pkgPaths ) {
133
+ if ( await hasPkgBin ( p , args [ 0 ] , flatOptions ) ) {
134
+ // we have to install the local package into the npx cache so that its
135
+ // bin links get set up
136
+ flatOptions . installLinks = false
137
+ // args[0] will exist when the package is installed
138
+ packages . push ( p )
139
+ yes = true
140
+ needPackageCommandSwap = false
141
+ break
142
+ }
121
143
}
122
- if ( localManifest ?. bin ?. [ args [ 0 ] ] ) {
123
- // we have to install the local package into the npx cache so that its
124
- // bin links get set up
125
- flatOptions . installLinks = false
126
- // args[0] will exist when the package is installed
127
- packages . push ( path )
128
- yes = true
129
- needPackageCommandSwap = false
130
- } else {
144
+ if ( needPackageCommandSwap ) {
145
+ // no bin entry in local packages or in tree, now we look for binPaths
131
146
const dir = dirname ( dirname ( localBin ) )
132
147
const localBinPath = await localFileExists ( dir , args [ 0 ] , '/' )
133
148
if ( localBinPath ) {
0 commit comments