@@ -28,35 +28,37 @@ const binPaths = []
28
28
const manifests = new Map ( )
29
29
30
30
const getManifest = async ( spec , flatOptions ) => {
31
- if ( ! manifests . get ( spec . raw ) ) {
31
+ if ( ! manifests . has ( spec . raw ) ) {
32
32
const manifest = await pacote . manifest ( spec , { ...flatOptions , preferOnline : true } )
33
33
manifests . set ( spec . raw , manifest )
34
34
}
35
35
return manifests . get ( spec . raw )
36
36
}
37
37
38
38
// Returns the required manifest if the spec is missing from the tree
39
+ // Returns the found node if it is in the tree
39
40
const missingFromTree = async ( { spec, tree, flatOptions } ) => {
40
41
if ( spec . registry && ( spec . rawSpec === '' || spec . type !== 'tag' ) ) {
41
42
// registry spec that is not a specific tag.
42
43
const nodesBySpec = tree . inventory . query ( 'packageName' , spec . name )
43
44
for ( const node of nodesBySpec ) {
44
45
if ( spec . type === 'tag' ) {
45
46
// package requested by name only
46
- return
47
+ return { node }
47
48
} else if ( spec . type === 'version' ) {
48
49
// package requested by specific version
49
50
if ( node . pkgid === spec . raw ) {
50
- return
51
+ return { node }
51
52
}
52
53
} else {
53
54
// package requested by version range, only remaining registry type
54
55
if ( semver . satisfies ( node . package . version , spec . rawSpec ) ) {
55
- return
56
+ return { node }
56
57
}
57
58
}
58
59
}
59
- return await getManifest ( spec , flatOptions )
60
+ const manifest = await getManifest ( spec , flatOptions )
61
+ return { manifest }
60
62
} else {
61
63
// non-registry spec, or a specific tag. Look up manifest and check
62
64
// resolved to see if it's in the tree.
@@ -65,10 +67,10 @@ const missingFromTree = async ({ spec, tree, flatOptions }) => {
65
67
for ( const node of nodesByManifest ) {
66
68
if ( node . package . resolved === manifest . _resolved ) {
67
69
// we have a package by the same name and the same resolved destination, nothing to add.
68
- return
70
+ return { node }
69
71
}
70
72
}
71
- return manifest
73
+ return { manifest }
72
74
}
73
75
}
74
76
@@ -132,35 +134,37 @@ const exec = async (opts) => {
132
134
133
135
// Find anything that isn't installed locally
134
136
const needInstall = [ ]
135
- await Promise . all ( packages . map ( async pkg => {
137
+ let commandManifest
138
+ await Promise . all ( packages . map ( async ( pkg , i ) => {
136
139
const spec = npa ( pkg , path )
137
- const manifest = await missingFromTree ( { spec, tree : localTree , flatOptions } )
140
+ const { manifest, node } = await missingFromTree ( { spec, tree : localTree , flatOptions } )
138
141
if ( manifest ) {
139
142
// Package does not exist in the local tree
140
143
needInstall . push ( { spec, manifest } )
144
+ if ( i === 0 ) {
145
+ commandManifest = manifest
146
+ }
147
+ } else if ( i === 0 ) {
148
+ // The node.package has enough to look up the bin
149
+ commandManifest = node . package
141
150
}
142
151
} ) )
143
152
144
153
if ( needPackageCommandSwap ) {
145
- // Either we have a scoped package or the bin of our package we inferred
146
- // from arg[0] might not be identical to the package name
147
154
const spec = npa ( args [ 0 ] )
148
- let commandManifest
149
- if ( needInstall . length === 0 ) {
150
- commandManifest = await getManifest ( spec , flatOptions )
151
- } else {
152
- commandManifest = needInstall [ 0 ] . manifest
153
- }
154
155
155
156
args [ 0 ] = getBinFromManifest ( commandManifest )
156
157
157
- // See if the package is installed globally, and run the translated bin
158
- const globalArb = new Arborist ( { ...flatOptions , path : globalPath , global : true } )
159
- const globalTree = await globalArb . loadActual ( )
160
- const globalManifest = await missingFromTree ( { spec, tree : globalTree , flatOptions } )
161
- if ( ! globalManifest ) {
162
- binPaths . push ( globalBin )
163
- return await run ( )
158
+ if ( needInstall . length > 0 ) {
159
+ // See if the package is installed globally, and run the translated bin
160
+ const globalArb = new Arborist ( { ...flatOptions , path : globalPath , global : true } )
161
+ const globalTree = await globalArb . loadActual ( )
162
+ const { manifest : globalManifest } =
163
+ await missingFromTree ( { spec, tree : globalTree , flatOptions } )
164
+ if ( ! globalManifest ) {
165
+ binPaths . push ( globalBin )
166
+ return await run ( )
167
+ }
164
168
}
165
169
}
166
170
@@ -183,7 +187,7 @@ const exec = async (opts) => {
183
187
} )
184
188
const npxTree = await npxArb . loadActual ( )
185
189
await Promise . all ( needInstall . map ( async ( { spec } ) => {
186
- const manifest = await missingFromTree ( { spec, tree : npxTree , flatOptions } )
190
+ const { manifest } = await missingFromTree ( { spec, tree : npxTree , flatOptions } )
187
191
if ( manifest ) {
188
192
// Manifest is not in npxCache, we need to install it there
189
193
if ( ! spec . registry ) {
0 commit comments