@@ -14,7 +14,7 @@ const getBinFromManifest = require('./get-bin-from-manifest.js')
1414const noTTY = require ( './no-tty.js' )
1515const runScript = require ( './run-script.js' )
1616const isWindows = require ( './is-windows.js' )
17- const { dirname, resolve } = require ( 'path' )
17+ const { dirname, resolve } = require ( 'node: path' )
1818
1919const binPaths = [ ]
2020
@@ -73,6 +73,11 @@ const missingFromTree = async ({ spec, tree, flatOptions, isNpxTree }) => {
7373 }
7474}
7575
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+
7681const exec = async ( opts ) => {
7782 const {
7883 args = [ ] ,
@@ -89,6 +94,13 @@ const exec = async (opts) => {
8994 ...flatOptions
9095 } = opts
9196
97+ let pkgPaths = opts . pkgPath
98+ if ( typeof pkgPaths === 'string' ) {
99+ pkgPaths = [ pkgPaths ]
100+ }
101+ if ( ! pkgPaths ) {
102+ pkgPaths = [ '.' ]
103+ }
92104 let yes = opts . yes
93105 const run = ( ) => runScript ( {
94106 args,
@@ -106,28 +118,31 @@ const exec = async (opts) => {
106118 return run ( )
107119 }
108120
121+ // Look in the local tree too
122+ pkgPaths . push ( path )
123+
109124 let needPackageCommandSwap = ( args . length > 0 ) && ( packages . length === 0 )
110125 // If they asked for a command w/o specifying a package, see if there is a
111126 // 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)
114129 // - globally
115130 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+ }
121143 }
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
131146 const dir = dirname ( dirname ( localBin ) )
132147 const localBinPath = await localFileExists ( dir , args [ 0 ] , '/' )
133148 if ( localBinPath ) {
0 commit comments