libnpmexec 4.0.2 → 4.0.5
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/README.md +1 -2
- package/lib/file-exists.js +1 -1
- package/lib/index.js +47 -26
- package/package.json +14 -13
- package/lib/manifest-missing.js +0 -19
package/README.md
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://npm.im/libnpmexec)
|
|
4
4
|
[](https://npm.im/libnpmexec)
|
|
5
|
-
[](https://coveralls.io/github/npm/libnpmexec?branch=main)
|
|
5
|
+
[](https://github.com/npm/cli/actions/workflows/ci-libnpmexec.yml)
|
|
7
6
|
|
|
8
7
|
The `npm exec` (`npx`) Programmatic API
|
|
9
8
|
|
package/lib/file-exists.js
CHANGED
|
@@ -4,7 +4,7 @@ const stat = promisify(require('fs').stat)
|
|
|
4
4
|
const walkUp = require('walk-up-path')
|
|
5
5
|
|
|
6
6
|
const fileExists = (file) => stat(file)
|
|
7
|
-
.then((
|
|
7
|
+
.then((res) => res.isFile())
|
|
8
8
|
.catch(() => false)
|
|
9
9
|
|
|
10
10
|
const localFileExists = async (dir, binName, root = '/') => {
|
package/lib/index.js
CHANGED
|
@@ -9,15 +9,14 @@ const npmlog = require('npmlog')
|
|
|
9
9
|
const mkdirp = require('mkdirp-infer-owner')
|
|
10
10
|
const npa = require('npm-package-arg')
|
|
11
11
|
const pacote = require('pacote')
|
|
12
|
-
const readPackageJson = require('read-package-json-fast')
|
|
13
12
|
|
|
14
13
|
const cacheInstallDir = require('./cache-install-dir.js')
|
|
15
14
|
const { fileExists, localFileExists } = require('./file-exists.js')
|
|
16
15
|
const getBinFromManifest = require('./get-bin-from-manifest.js')
|
|
17
|
-
const manifestMissing = require('./manifest-missing.js')
|
|
18
16
|
const noTTY = require('./no-tty.js')
|
|
19
17
|
const runScript = require('./run-script.js')
|
|
20
18
|
const isWindows = require('./is-windows.js')
|
|
19
|
+
const _localManifest = Symbol('localManifest')
|
|
21
20
|
|
|
22
21
|
/* istanbul ignore next */
|
|
23
22
|
const PATH = (
|
|
@@ -86,20 +85,42 @@ const exec = async (opts) => {
|
|
|
86
85
|
packages.push(args[0])
|
|
87
86
|
}
|
|
88
87
|
|
|
88
|
+
// figure out whether we need to install stuff, or if local is fine
|
|
89
|
+
const localArb = new Arborist({
|
|
90
|
+
...flatOptions,
|
|
91
|
+
path,
|
|
92
|
+
})
|
|
93
|
+
const localTree = await localArb.loadActual()
|
|
94
|
+
|
|
95
|
+
const getLocalManifest = ({ tree, name }) => {
|
|
96
|
+
// look up the package name in the current tree inventory,
|
|
97
|
+
// if it's found then return that normalized pkg data
|
|
98
|
+
const [node] = tree.inventory.query('packageName', name)
|
|
99
|
+
|
|
100
|
+
if (node) {
|
|
101
|
+
return {
|
|
102
|
+
_id: node.pkgid,
|
|
103
|
+
...node.package,
|
|
104
|
+
[_localManifest]: true,
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
89
109
|
// If we do `npm exec foo`, and have a `foo` locally, then we'll
|
|
90
110
|
// always use that, so we don't really need to fetch the manifest.
|
|
91
111
|
// So: run npa on each packages entry, and if it is a name with a
|
|
92
|
-
// rawSpec==='', then try to
|
|
93
|
-
//
|
|
94
|
-
// that fails.
|
|
112
|
+
// rawSpec==='', then try to find that node name in the tree inventory
|
|
113
|
+
// and only pacote fetch if that fails.
|
|
95
114
|
const manis = await Promise.all(packages.map(async p => {
|
|
96
115
|
const spec = npa(p, path)
|
|
97
116
|
if (spec.type === 'tag' && spec.rawSpec === '') {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
117
|
+
const localManifest = getLocalManifest({
|
|
118
|
+
tree: localTree,
|
|
119
|
+
name: spec.name,
|
|
120
|
+
})
|
|
121
|
+
if (localManifest) {
|
|
122
|
+
return localManifest
|
|
123
|
+
}
|
|
103
124
|
}
|
|
104
125
|
// Force preferOnline to true so we are making sure to pull in the latest
|
|
105
126
|
// This is especially useful if the user didn't give us a version, and
|
|
@@ -114,16 +135,9 @@ const exec = async (opts) => {
|
|
|
114
135
|
args[0] = getBinFromManifest(manis[0])
|
|
115
136
|
}
|
|
116
137
|
|
|
117
|
-
//
|
|
118
|
-
const localArb = new Arborist({
|
|
119
|
-
...flatOptions,
|
|
120
|
-
path,
|
|
121
|
-
})
|
|
122
|
-
const tree = await localArb.loadActual()
|
|
123
|
-
|
|
124
|
-
// do we have all the packages in manifest list?
|
|
138
|
+
// are all packages from the manifest list installed?
|
|
125
139
|
const needInstall =
|
|
126
|
-
manis.some(manifest =>
|
|
140
|
+
manis.some(manifest => !manifest[_localManifest])
|
|
127
141
|
|
|
128
142
|
if (needInstall) {
|
|
129
143
|
const { npxCache } = flatOptions
|
|
@@ -135,16 +149,23 @@ const exec = async (opts) => {
|
|
|
135
149
|
})
|
|
136
150
|
const tree = await arb.loadActual()
|
|
137
151
|
|
|
152
|
+
// inspect the npx-space installed tree to check if the package is already
|
|
153
|
+
// there, if that's the case also check that it's version matches the same
|
|
154
|
+
// version expected by the user requested pkg returned by pacote.manifest
|
|
155
|
+
const filterMissingPackagesFromInstallDir = (mani) => {
|
|
156
|
+
const localManifest = getLocalManifest({ tree, name: mani.name })
|
|
157
|
+
if (localManifest) {
|
|
158
|
+
return localManifest.version !== mani.version
|
|
159
|
+
}
|
|
160
|
+
return true
|
|
161
|
+
}
|
|
162
|
+
|
|
138
163
|
// at this point, we have to ensure that we get the exact same
|
|
139
164
|
// version, because it's something that has only ever been installed
|
|
140
165
|
// by npm exec in the cache install directory
|
|
141
|
-
const add = manis
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
...mani,
|
|
145
|
-
_from: `${mani.name}@${mani.version}`,
|
|
146
|
-
},
|
|
147
|
-
}))
|
|
166
|
+
const add = manis
|
|
167
|
+
.filter(mani => !mani[_localManifest])
|
|
168
|
+
.filter(filterMissingPackagesFromInstallDir)
|
|
148
169
|
.map(mani => mani._from)
|
|
149
170
|
.sort((a, b) => a.localeCompare(b, 'en'))
|
|
150
171
|
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "libnpmexec",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.5",
|
|
4
4
|
"files": [
|
|
5
|
-
"bin",
|
|
6
|
-
"lib"
|
|
5
|
+
"bin/",
|
|
6
|
+
"lib/"
|
|
7
7
|
],
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"engines": {
|
|
10
|
-
"node": "^12.13.0 || ^14.15.0 || >=16"
|
|
10
|
+
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
|
11
11
|
},
|
|
12
12
|
"description": "npm exec (npx) programmatic API",
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
|
-
"url": "https://github.com/npm/cli",
|
|
15
|
+
"url": "https://github.com/npm/cli.git",
|
|
16
16
|
"directory": "workspaces/libnpmexec"
|
|
17
17
|
},
|
|
18
18
|
"keywords": [
|
|
@@ -33,26 +33,26 @@
|
|
|
33
33
|
],
|
|
34
34
|
"license": "ISC",
|
|
35
35
|
"scripts": {
|
|
36
|
-
"lint": "eslint
|
|
36
|
+
"lint": "eslint \"**/*.js\"",
|
|
37
37
|
"posttest": "npm run lint",
|
|
38
38
|
"test": "tap",
|
|
39
39
|
"snap": "tap",
|
|
40
40
|
"preversion": "npm test",
|
|
41
41
|
"postversion": "npm publish",
|
|
42
42
|
"prepublishOnly": "git push origin --follow-tags",
|
|
43
|
-
"postlint": "
|
|
43
|
+
"postlint": "template-oss-check",
|
|
44
44
|
"lintfix": "npm run lint -- --fix",
|
|
45
|
-
"template-
|
|
45
|
+
"template-oss-apply": "template-oss-apply --force"
|
|
46
46
|
},
|
|
47
47
|
"tap": {
|
|
48
48
|
"color": true,
|
|
49
|
-
"check-coverage": true,
|
|
50
49
|
"files": "test/*.js"
|
|
51
50
|
},
|
|
52
51
|
"devDependencies": {
|
|
53
|
-
"@npmcli/
|
|
52
|
+
"@npmcli/eslint-config": "^3.0.1",
|
|
53
|
+
"@npmcli/template-oss": "3.4.2",
|
|
54
54
|
"bin-links": "^3.0.0",
|
|
55
|
-
"tap": "^
|
|
55
|
+
"tap": "^16.0.1"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@npmcli/arborist": "^5.0.0",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"chalk": "^4.1.0",
|
|
62
62
|
"mkdirp-infer-owner": "^2.0.0",
|
|
63
63
|
"npm-package-arg": "^9.0.1",
|
|
64
|
-
"npmlog": "^6.0.
|
|
64
|
+
"npmlog": "^6.0.2",
|
|
65
65
|
"pacote": "^13.0.5",
|
|
66
66
|
"proc-log": "^2.0.0",
|
|
67
67
|
"read": "^1.0.7",
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"walk-up-path": "^1.0.0"
|
|
70
70
|
},
|
|
71
71
|
"templateOSS": {
|
|
72
|
-
"
|
|
72
|
+
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
|
|
73
|
+
"version": "3.4.2"
|
|
73
74
|
}
|
|
74
75
|
}
|
package/lib/manifest-missing.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
const manifestMissing = ({ tree, manifest }) => {
|
|
2
|
-
// if the tree doesn't have a child by that name/version, return true
|
|
3
|
-
// true means we need to install it
|
|
4
|
-
const child = tree.children.get(manifest.name)
|
|
5
|
-
// if no child, we have to load it
|
|
6
|
-
if (!child) {
|
|
7
|
-
return true
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
// if no version/tag specified, allow whatever's there
|
|
11
|
-
if (manifest._from === `${manifest.name}@`) {
|
|
12
|
-
return false
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// otherwise the version has to match what we WOULD get
|
|
16
|
-
return child.version !== manifest.version
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
module.exports = manifestMissing
|