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 +57 -28
- package/lib/run-script.js +1 -0
- package/package.json +8 -6
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
149
|
-
if (
|
|
150
|
-
|
|
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
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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.
|
|
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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "libnpmexec",
|
|
3
|
-
"version": "4.0.
|
|
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
|
|
53
|
-
"@npmcli/template-oss": "3.
|
|
54
|
-
"bin-links": "^3.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.
|
|
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.
|
|
77
|
+
"version": "3.8.0"
|
|
76
78
|
}
|
|
77
79
|
}
|