libnpmexec 4.0.9 → 4.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -28,7 +28,7 @@ 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
  }
@@ -36,6 +36,7 @@ const getManifest = async (spec, flatOptions) => {
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.
@@ -43,32 +44,36 @@ const missingFromTree = async ({ spec, tree, flatOptions }) => {
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.
63
65
  const manifest = await getManifest(spec, flatOptions)
66
+ if (spec.type === 'directory') {
67
+ return { manifest }
68
+ }
64
69
  const nodesByManifest = tree.inventory.query('packageName', manifest.name)
65
70
  for (const node of nodesByManifest) {
66
71
  if (node.package.resolved === manifest._resolved) {
67
72
  // we have a package by the same name and the same resolved destination, nothing to add.
68
- return
73
+ return { node }
69
74
  }
70
75
  }
71
- return manifest
76
+ return { manifest }
72
77
  }
73
78
  }
74
79
 
@@ -80,17 +85,17 @@ const exec = async (opts) => {
80
85
  localBin = resolve('./node_modules/.bin'),
81
86
  locationMsg = undefined,
82
87
  globalBin = '',
83
- globalPath = '',
88
+ globalPath,
84
89
  output,
85
90
  // dereference values because we manipulate it later
86
91
  packages: [...packages] = [],
87
92
  path = '.',
88
93
  runPath = '.',
89
94
  scriptShell = isWindows ? process.env.ComSpec || 'cmd' : 'sh',
90
- yes = undefined,
91
95
  ...flatOptions
92
96
  } = opts
93
97
 
98
+ let yes = opts.yes
94
99
  const run = () => runScript({
95
100
  args,
96
101
  call,
@@ -118,7 +123,7 @@ const exec = async (opts) => {
118
123
  if (localBinPath) {
119
124
  binPaths.push(localBinPath)
120
125
  return await run()
121
- } else if (await fileExists(`${globalBin}/${args[0]}`)) {
126
+ } else if (globalPath && await fileExists(`${globalBin}/${args[0]}`)) {
122
127
  binPaths.push(globalBin)
123
128
  return await run()
124
129
  }
@@ -127,40 +132,56 @@ const exec = async (opts) => {
127
132
  packages.push(args[0])
128
133
  }
129
134
 
135
+ // Resolve any directory specs so that the npx directory is unique to the
136
+ // resolved directory, not the potentially relative one (i.e. "npx .")
137
+ for (const i in packages) {
138
+ const pkg = packages[i]
139
+ const spec = npa(pkg)
140
+ if (spec.type === 'directory') {
141
+ packages[i] = spec.fetchSpec
142
+ }
143
+ }
144
+
130
145
  const localArb = new Arborist({ ...flatOptions, path })
131
146
  const localTree = await localArb.loadActual()
132
147
 
133
148
  // Find anything that isn't installed locally
134
149
  const needInstall = []
135
- await Promise.all(packages.map(async pkg => {
150
+ let commandManifest
151
+ await Promise.all(packages.map(async (pkg, i) => {
136
152
  const spec = npa(pkg, path)
137
- const manifest = await missingFromTree({ spec, tree: localTree, flatOptions })
153
+ const { manifest, node } = await missingFromTree({ spec, tree: localTree, flatOptions })
138
154
  if (manifest) {
139
155
  // Package does not exist in the local tree
140
156
  needInstall.push({ spec, manifest })
157
+ if (i === 0) {
158
+ commandManifest = manifest
159
+ }
160
+ } else if (i === 0) {
161
+ // The node.package has enough to look up the bin
162
+ commandManifest = node.package
141
163
  }
142
164
  }))
143
165
 
144
166
  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
167
  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
168
+
169
+ if (spec.type === 'directory') {
170
+ yes = true
153
171
  }
154
172
 
155
173
  args[0] = getBinFromManifest(commandManifest)
156
174
 
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()
175
+ if (needInstall.length > 0 && globalPath) {
176
+ // See if the package is installed globally, and run the translated bin
177
+ const globalArb = new Arborist({ ...flatOptions, path: globalPath, global: true })
178
+ const globalTree = await globalArb.loadActual()
179
+ const { manifest: globalManifest } =
180
+ await missingFromTree({ spec, tree: globalTree, flatOptions })
181
+ if (!globalManifest && await fileExists(`${globalBin}/${args[0]}`)) {
182
+ binPaths.push(globalBin)
183
+ return await run()
184
+ }
164
185
  }
165
186
  }
166
187
 
@@ -172,7 +193,15 @@ const exec = async (opts) => {
172
193
  throw new Error('Must provide a valid npxCache path')
173
194
  }
174
195
  const hash = crypto.createHash('sha512')
175
- .update(packages.sort((a, b) => a.localeCompare(b, 'en')).join('\n'))
196
+ .update(packages.map(p => {
197
+ // Keeps the npx directory unique to the resolved directory, not the
198
+ // potentially relative one (i.e. "npx .")
199
+ const spec = npa(p)
200
+ if (spec.type === 'directory') {
201
+ return spec.fetchSpec
202
+ }
203
+ return p
204
+ }).sort((a, b) => a.localeCompare(b, 'en')).join('\n'))
176
205
  .digest('hex')
177
206
  .slice(0, 16)
178
207
  const installDir = resolve(npxCache, hash)
@@ -183,7 +212,7 @@ const exec = async (opts) => {
183
212
  })
184
213
  const npxTree = await npxArb.loadActual()
185
214
  await Promise.all(needInstall.map(async ({ spec }) => {
186
- const manifest = await missingFromTree({ spec, tree: npxTree, flatOptions })
215
+ const { manifest } = await missingFromTree({ spec, tree: npxTree, flatOptions })
187
216
  if (manifest) {
188
217
  // Manifest is not in npxCache, we need to install it there
189
218
  if (!spec.registry) {
package/lib/run-script.js CHANGED
@@ -73,6 +73,7 @@ const run = async ({
73
73
  event: 'npx',
74
74
  args,
75
75
  stdio: 'inherit',
76
+ scriptShell,
76
77
  })
77
78
  } finally {
78
79
  npmlog.enableProgress()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libnpmexec",
3
- "version": "4.0.9",
3
+ "version": "4.0.12",
4
4
  "files": [
5
5
  "bin/",
6
6
  "lib/"
@@ -49,13 +49,15 @@
49
49
  "files": "test/*.js"
50
50
  },
51
51
  "devDependencies": {
52
- "@npmcli/eslint-config": "^3.0.1",
53
- "@npmcli/template-oss": "3.5.0",
54
- "bin-links": "^3.0.0",
52
+ "@npmcli/eslint-config": "^3.1.0",
53
+ "@npmcli/template-oss": "3.8.0",
54
+ "bin-links": "^3.0.3",
55
+ "minify-registry-metadata": "^2.2.0",
56
+ "mkdirp": "^1.0.4",
55
57
  "tap": "^16.0.1"
56
58
  },
57
59
  "dependencies": {
58
- "@npmcli/arborist": "^5.0.0",
60
+ "@npmcli/arborist": "^5.6.1",
59
61
  "@npmcli/ci-detect": "^2.0.0",
60
62
  "@npmcli/fs": "^2.1.1",
61
63
  "@npmcli/run-script": "^4.2.0",
@@ -72,6 +74,6 @@
72
74
  },
73
75
  "templateOSS": {
74
76
  "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
75
- "version": "3.5.0"
77
+ "version": "3.8.0"
76
78
  }
77
79
  }