@npmcli/arborist 5.0.5 → 5.1.1
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/arborist/build-ideal-tree.js +15 -7
- package/lib/arborist/load-actual.js +1 -0
- package/lib/arborist/load-virtual.js +2 -0
- package/lib/audit-report.js +36 -39
- package/lib/dep-valid.js +13 -3
- package/lib/edge.js +5 -0
- package/lib/node.js +8 -0
- package/lib/place-dep.js +3 -0
- package/package.json +7 -7
|
@@ -124,6 +124,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
124
124
|
globalStyle = false,
|
|
125
125
|
idealTree = null,
|
|
126
126
|
includeWorkspaceRoot = false,
|
|
127
|
+
installLinks = false,
|
|
127
128
|
legacyPeerDeps = false,
|
|
128
129
|
packageLock = true,
|
|
129
130
|
strictPeerDeps = false,
|
|
@@ -135,6 +136,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
135
136
|
this[_strictPeerDeps] = !!strictPeerDeps
|
|
136
137
|
|
|
137
138
|
this.idealTree = idealTree
|
|
139
|
+
this.installLinks = installLinks
|
|
138
140
|
this.legacyPeerDeps = legacyPeerDeps
|
|
139
141
|
|
|
140
142
|
this[_usePackageLock] = packageLock
|
|
@@ -410,6 +412,7 @@ Try using the package name instead, e.g:
|
|
|
410
412
|
peer: false,
|
|
411
413
|
optional: false,
|
|
412
414
|
global: this[_global],
|
|
415
|
+
installLinks: this.installLinks,
|
|
413
416
|
legacyPeerDeps: this.legacyPeerDeps,
|
|
414
417
|
loadOverrides: true,
|
|
415
418
|
})
|
|
@@ -424,6 +427,7 @@ Try using the package name instead, e.g:
|
|
|
424
427
|
peer: false,
|
|
425
428
|
optional: false,
|
|
426
429
|
global: this[_global],
|
|
430
|
+
installLinks: this.installLinks,
|
|
427
431
|
legacyPeerDeps: this.legacyPeerDeps,
|
|
428
432
|
root,
|
|
429
433
|
})
|
|
@@ -992,6 +996,7 @@ This is a one-time fix-up, please be patient...
|
|
|
992
996
|
preferDedupe: this[_preferDedupe],
|
|
993
997
|
legacyBundling: this[_legacyBundling],
|
|
994
998
|
strictPeerDeps: this[_strictPeerDeps],
|
|
999
|
+
installLinks: this.installLinks,
|
|
995
1000
|
legacyPeerDeps: this.legacyPeerDeps,
|
|
996
1001
|
globalStyle: this[_globalStyle],
|
|
997
1002
|
}))
|
|
@@ -1151,6 +1156,7 @@ This is a one-time fix-up, please be patient...
|
|
|
1151
1156
|
const vr = new Node({
|
|
1152
1157
|
path: node.realpath,
|
|
1153
1158
|
sourceReference: node,
|
|
1159
|
+
installLinks: this.installLinks,
|
|
1154
1160
|
legacyPeerDeps: this.legacyPeerDeps,
|
|
1155
1161
|
overrides: node.overrides,
|
|
1156
1162
|
})
|
|
@@ -1268,17 +1274,18 @@ This is a one-time fix-up, please be patient...
|
|
|
1268
1274
|
// the object so it doesn't get mutated.
|
|
1269
1275
|
// Don't bother to load the manifest for link deps, because the target
|
|
1270
1276
|
// might be within another package that doesn't exist yet.
|
|
1271
|
-
const { legacyPeerDeps } = this
|
|
1277
|
+
const { installLinks, legacyPeerDeps } = this
|
|
1278
|
+
const isWorkspace = this.idealTree.workspaces && this.idealTree.workspaces.has(spec.name)
|
|
1272
1279
|
|
|
1273
|
-
// spec is a directory, link it
|
|
1274
|
-
if (spec.type === 'directory') {
|
|
1280
|
+
// spec is a directory, link it unless installLinks is set or it's a workspace
|
|
1281
|
+
if (spec.type === 'directory' && (isWorkspace || !installLinks)) {
|
|
1275
1282
|
return this[_linkFromSpec](name, spec, parent, edge)
|
|
1276
1283
|
}
|
|
1277
1284
|
|
|
1278
1285
|
// if the spec matches a workspace name, then see if the workspace node will
|
|
1279
1286
|
// satisfy the edge. if it does, we return the workspace node to make sure it
|
|
1280
1287
|
// takes priority.
|
|
1281
|
-
if (
|
|
1288
|
+
if (isWorkspace) {
|
|
1282
1289
|
const existingNode = this.idealTree.edgesOut.get(spec.name).to
|
|
1283
1290
|
if (existingNode && existingNode.isWorkspace && existingNode.satisfies(edge)) {
|
|
1284
1291
|
return edge.to
|
|
@@ -1288,7 +1295,7 @@ This is a one-time fix-up, please be patient...
|
|
|
1288
1295
|
// spec isn't a directory, and either isn't a workspace or the workspace we have
|
|
1289
1296
|
// doesn't satisfy the edge. try to fetch a manifest and build a node from that.
|
|
1290
1297
|
return this[_fetchManifest](spec)
|
|
1291
|
-
.then(pkg => new Node({ name, pkg, parent, legacyPeerDeps }), error => {
|
|
1298
|
+
.then(pkg => new Node({ name, pkg, parent, installLinks, legacyPeerDeps }), error => {
|
|
1292
1299
|
error.requiredBy = edge.from.location || '.'
|
|
1293
1300
|
|
|
1294
1301
|
// failed to load the spec, either because of enotarget or
|
|
@@ -1298,6 +1305,7 @@ This is a one-time fix-up, please be patient...
|
|
|
1298
1305
|
name,
|
|
1299
1306
|
parent,
|
|
1300
1307
|
error,
|
|
1308
|
+
installLinks,
|
|
1301
1309
|
legacyPeerDeps,
|
|
1302
1310
|
})
|
|
1303
1311
|
this[_loadFailures].add(n)
|
|
@@ -1307,9 +1315,9 @@ This is a one-time fix-up, please be patient...
|
|
|
1307
1315
|
|
|
1308
1316
|
[_linkFromSpec] (name, spec, parent, edge) {
|
|
1309
1317
|
const realpath = spec.fetchSpec
|
|
1310
|
-
const { legacyPeerDeps } = this
|
|
1318
|
+
const { installLinks, legacyPeerDeps } = this
|
|
1311
1319
|
return rpj(realpath + '/package.json').catch(() => ({})).then(pkg => {
|
|
1312
|
-
const link = new Link({ name, parent, realpath, pkg, legacyPeerDeps })
|
|
1320
|
+
const link = new Link({ name, parent, realpath, pkg, installLinks, legacyPeerDeps })
|
|
1313
1321
|
this[_linkNodes].add(link)
|
|
1314
1322
|
return link
|
|
1315
1323
|
})
|
|
@@ -283,6 +283,7 @@ module.exports = cls => class ActualLoader extends cls {
|
|
|
283
283
|
.then(pkg => [pkg, null], error => [null, error])
|
|
284
284
|
.then(([pkg, error]) => {
|
|
285
285
|
return this[normalize(path) === real ? _newNode : _newLink]({
|
|
286
|
+
installLinks: this.installLinks,
|
|
286
287
|
legacyPeerDeps: this.legacyPeerDeps,
|
|
287
288
|
path,
|
|
288
289
|
realpath: real,
|
|
@@ -278,6 +278,7 @@ module.exports = cls => class VirtualLoader extends cls {
|
|
|
278
278
|
const peer = sw.peer
|
|
279
279
|
|
|
280
280
|
const node = new Node({
|
|
281
|
+
installLinks: this.installLinks,
|
|
281
282
|
legacyPeerDeps: this.legacyPeerDeps,
|
|
282
283
|
root: this.virtualTree,
|
|
283
284
|
path,
|
|
@@ -304,6 +305,7 @@ module.exports = cls => class VirtualLoader extends cls {
|
|
|
304
305
|
[loadLink] (location, targetLoc, target, meta) {
|
|
305
306
|
const path = resolve(this.path, location)
|
|
306
307
|
const link = new Link({
|
|
308
|
+
installLinks: this.installLinks,
|
|
307
309
|
legacyPeerDeps: this.legacyPeerDeps,
|
|
308
310
|
path,
|
|
309
311
|
realpath: resolve(this.path, targetLoc),
|
package/lib/audit-report.js
CHANGED
|
@@ -134,16 +134,7 @@ class AuditReport extends Map {
|
|
|
134
134
|
const seen = new Set()
|
|
135
135
|
for (const advisory of advisories) {
|
|
136
136
|
const { name, range } = advisory
|
|
137
|
-
|
|
138
|
-
// don't flag the exact same name/range more than once
|
|
139
|
-
// adding multiple advisories with the same range is fine, but no
|
|
140
|
-
// need to search for nodes we already would have added.
|
|
141
137
|
const k = `${name}@${range}`
|
|
142
|
-
if (seen.has(k)) {
|
|
143
|
-
continue
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
seen.add(k)
|
|
147
138
|
|
|
148
139
|
const vuln = this.get(name) || new Vuln({ name, advisory })
|
|
149
140
|
if (this.has(name)) {
|
|
@@ -151,44 +142,50 @@ class AuditReport extends Map {
|
|
|
151
142
|
}
|
|
152
143
|
super.set(name, vuln)
|
|
153
144
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
145
|
+
// don't flag the exact same name/range more than once
|
|
146
|
+
// adding multiple advisories with the same range is fine, but no
|
|
147
|
+
// need to search for nodes we already would have added.
|
|
148
|
+
if (!seen.has(k)) {
|
|
149
|
+
const p = []
|
|
150
|
+
for (const node of this.tree.inventory.query('packageName', name)) {
|
|
151
|
+
if (!shouldAudit(node, this[_omit], this.filterSet)) {
|
|
152
|
+
continue
|
|
153
|
+
}
|
|
159
154
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
155
|
+
// if not vulnerable by this advisory, keep searching
|
|
156
|
+
if (!advisory.testVersion(node.version)) {
|
|
157
|
+
continue
|
|
158
|
+
}
|
|
164
159
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
160
|
+
// we will have loaded the source already if this is a metavuln
|
|
161
|
+
if (advisory.type === 'metavuln') {
|
|
162
|
+
vuln.addVia(this.get(advisory.dependency))
|
|
163
|
+
}
|
|
169
164
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
165
|
+
// already marked this one, no need to do it again
|
|
166
|
+
if (vuln.nodes.has(node)) {
|
|
167
|
+
continue
|
|
168
|
+
}
|
|
174
169
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
170
|
+
// haven't marked this one yet. get its dependents.
|
|
171
|
+
vuln.nodes.add(node)
|
|
172
|
+
for (const { from: dep, spec } of node.edgesIn) {
|
|
173
|
+
if (dep.isTop && !vuln.topNodes.has(dep)) {
|
|
174
|
+
this[_checkTopNode](dep, vuln, spec)
|
|
175
|
+
} else {
|
|
181
176
|
// calculate a metavuln, if necessary
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
177
|
+
const calc = this.calculator.calculate(dep.packageName, advisory)
|
|
178
|
+
p.push(calc.then(meta => {
|
|
179
|
+
if (meta.testVersion(dep.version, spec)) {
|
|
180
|
+
advisories.add(meta)
|
|
181
|
+
}
|
|
182
|
+
}))
|
|
183
|
+
}
|
|
188
184
|
}
|
|
189
185
|
}
|
|
186
|
+
await Promise.all(p)
|
|
187
|
+
seen.add(k)
|
|
190
188
|
}
|
|
191
|
-
await Promise.all(p)
|
|
192
189
|
|
|
193
190
|
// make sure we actually got something. if not, remove it
|
|
194
191
|
// this can happen if you are loading from a lockfile created by
|
package/lib/dep-valid.js
CHANGED
|
@@ -53,9 +53,7 @@ const depValid = (child, requested, requestor) => {
|
|
|
53
53
|
return semver.satisfies(child.version, requested.fetchSpec, true)
|
|
54
54
|
|
|
55
55
|
case 'directory':
|
|
56
|
-
|
|
57
|
-
return !!child.isLink &&
|
|
58
|
-
relative(child.realpath, requested.fetchSpec) === ''
|
|
56
|
+
return linkValid(child, requested, requestor)
|
|
59
57
|
|
|
60
58
|
case 'file':
|
|
61
59
|
return tarballValid(child, requested, requestor)
|
|
@@ -108,6 +106,18 @@ const depValid = (child, requested, requestor) => {
|
|
|
108
106
|
return false
|
|
109
107
|
}
|
|
110
108
|
|
|
109
|
+
const linkValid = (child, requested, requestor) => {
|
|
110
|
+
const isLink = !!child.isLink
|
|
111
|
+
// if we're installing links and the node is a link, then it's invalid because we want
|
|
112
|
+
// a real node to be there
|
|
113
|
+
if (requestor.installLinks) {
|
|
114
|
+
return !isLink
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// directory must be a link to the specified folder
|
|
118
|
+
return isLink && relative(child.realpath, requested.fetchSpec) === ''
|
|
119
|
+
}
|
|
120
|
+
|
|
111
121
|
const tarballValid = (child, requested, requestor) => {
|
|
112
122
|
if (child.isLink) {
|
|
113
123
|
return false
|
package/lib/edge.js
CHANGED
|
@@ -215,6 +215,11 @@ class Edge {
|
|
|
215
215
|
|
|
216
216
|
reload (hard = false) {
|
|
217
217
|
this[_explanation] = null
|
|
218
|
+
if (this[_from].overrides) {
|
|
219
|
+
this.overrides = this[_from].overrides.getEdgeRule(this)
|
|
220
|
+
} else {
|
|
221
|
+
delete this.overrides
|
|
222
|
+
}
|
|
218
223
|
const newTo = this[_from].resolve(this.name)
|
|
219
224
|
if (newTo !== this[_to]) {
|
|
220
225
|
if (this[_to]) {
|
package/lib/node.js
CHANGED
|
@@ -86,6 +86,7 @@ class Node {
|
|
|
86
86
|
name,
|
|
87
87
|
children,
|
|
88
88
|
fsChildren,
|
|
89
|
+
installLinks = false,
|
|
89
90
|
legacyPeerDeps = false,
|
|
90
91
|
linksIn,
|
|
91
92
|
hasShrinkwrap,
|
|
@@ -152,6 +153,7 @@ class Node {
|
|
|
152
153
|
}
|
|
153
154
|
this.integrity = integrity || pkg._integrity || null
|
|
154
155
|
this.hasShrinkwrap = hasShrinkwrap || pkg._hasShrinkwrap || false
|
|
156
|
+
this.installLinks = installLinks
|
|
155
157
|
this.legacyPeerDeps = legacyPeerDeps
|
|
156
158
|
|
|
157
159
|
this.children = new CaseInsensitiveMap()
|
|
@@ -792,6 +794,9 @@ class Node {
|
|
|
792
794
|
target.root = root
|
|
793
795
|
}
|
|
794
796
|
|
|
797
|
+
if (!this.overrides && this.parent && this.parent.overrides) {
|
|
798
|
+
this.overrides = this.parent.overrides.getNodeRule(this)
|
|
799
|
+
}
|
|
795
800
|
// tree should always be valid upon root setter completion.
|
|
796
801
|
treeCheck(this)
|
|
797
802
|
treeCheck(root)
|
|
@@ -1146,6 +1151,9 @@ class Node {
|
|
|
1146
1151
|
for (const kid of node.children.values()) {
|
|
1147
1152
|
kid.parent = this
|
|
1148
1153
|
}
|
|
1154
|
+
if (node.isLink && node.target) {
|
|
1155
|
+
node.target.root = null
|
|
1156
|
+
}
|
|
1149
1157
|
}
|
|
1150
1158
|
|
|
1151
1159
|
if (!node.isRoot) {
|
package/lib/place-dep.js
CHANGED
|
@@ -45,6 +45,7 @@ class PlaceDep {
|
|
|
45
45
|
auditReport,
|
|
46
46
|
legacyBundling,
|
|
47
47
|
strictPeerDeps,
|
|
48
|
+
installLinks,
|
|
48
49
|
legacyPeerDeps,
|
|
49
50
|
globalStyle,
|
|
50
51
|
} = parent || options
|
|
@@ -56,6 +57,7 @@ class PlaceDep {
|
|
|
56
57
|
auditReport,
|
|
57
58
|
legacyBundling,
|
|
58
59
|
strictPeerDeps,
|
|
60
|
+
installLinks,
|
|
59
61
|
legacyPeerDeps,
|
|
60
62
|
globalStyle,
|
|
61
63
|
})
|
|
@@ -293,6 +295,7 @@ class PlaceDep {
|
|
|
293
295
|
pkg: dep.package,
|
|
294
296
|
resolved: dep.resolved,
|
|
295
297
|
integrity: dep.integrity,
|
|
298
|
+
installLinks: this.installLinks,
|
|
296
299
|
legacyPeerDeps: this.legacyPeerDeps,
|
|
297
300
|
error: dep.errors[0],
|
|
298
301
|
...(dep.overrides ? { overrides: dep.overrides } : {}),
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@npmcli/arborist",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.1.1",
|
|
4
4
|
"description": "Manage node_modules trees",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@isaacs/string-locale-compare": "^1.1.0",
|
|
7
7
|
"@npmcli/installed-package-contents": "^1.0.7",
|
|
8
|
-
"@npmcli/map-workspaces": "^2.0.
|
|
8
|
+
"@npmcli/map-workspaces": "^2.0.3",
|
|
9
9
|
"@npmcli/metavuln-calculator": "^3.0.1",
|
|
10
10
|
"@npmcli/move-file": "^2.0.0",
|
|
11
11
|
"@npmcli/name-from-folder": "^1.0.1",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"@npmcli/package-json": "^2.0.0",
|
|
14
14
|
"@npmcli/run-script": "^3.0.0",
|
|
15
15
|
"bin-links": "^3.0.0",
|
|
16
|
-
"cacache": "^16.0.
|
|
16
|
+
"cacache": "^16.0.6",
|
|
17
17
|
"common-ancestor-path": "^1.0.1",
|
|
18
18
|
"json-parse-even-better-errors": "^2.3.1",
|
|
19
19
|
"json-stringify-nice": "^1.1.4",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"npm-package-arg": "^9.0.0",
|
|
25
25
|
"npm-pick-manifest": "^7.0.0",
|
|
26
26
|
"npm-registry-fetch": "^13.0.0",
|
|
27
|
-
"npmlog": "^6.0.
|
|
27
|
+
"npmlog": "^6.0.2",
|
|
28
28
|
"pacote": "^13.0.5",
|
|
29
29
|
"parse-conflict-json": "^2.0.1",
|
|
30
30
|
"proc-log": "^2.0.0",
|
|
@@ -33,14 +33,14 @@
|
|
|
33
33
|
"read-package-json-fast": "^2.0.2",
|
|
34
34
|
"readdir-scoped-modules": "^1.1.0",
|
|
35
35
|
"rimraf": "^3.0.2",
|
|
36
|
-
"semver": "^7.3.
|
|
36
|
+
"semver": "^7.3.7",
|
|
37
37
|
"ssri": "^9.0.0",
|
|
38
38
|
"treeverse": "^2.0.0",
|
|
39
39
|
"walk-up-path": "^1.0.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@npmcli/eslint-config": "^3.0.1",
|
|
43
|
-
"@npmcli/template-oss": "3.
|
|
43
|
+
"@npmcli/template-oss": "3.4.2",
|
|
44
44
|
"benchmark": "^2.1.4",
|
|
45
45
|
"chalk": "^4.1.0",
|
|
46
46
|
"minify-registry-metadata": "^2.1.0",
|
|
@@ -101,6 +101,6 @@
|
|
|
101
101
|
},
|
|
102
102
|
"templateOSS": {
|
|
103
103
|
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
|
|
104
|
-
"version": "3.
|
|
104
|
+
"version": "3.4.2"
|
|
105
105
|
}
|
|
106
106
|
}
|